Re: [PATCH] cifs-utils: handle cifs_idmap type of key to map a SID to either an uid or gid (try #5)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Feb 15, 2011 at 2:45 PM, Jeff Layton <jlayton@xxxxxxxxxx> wrote:
> On Fri, 11 Feb 2011 12:49:09 -0600
> shirishpargaonkar@xxxxxxxxx wrote:
>
>> From: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
>>
>>
>> Handle cifs_idmap type of key. Extract a SID string from the description
>> and map it to either an uid or gid using winbind APIs.
>> If that fails (e.g. because winbind is not installed/running or winbind returns
>> an error), try to obtain uid of 'nobody' and gid of 'nogroup'.
>> And if that fails, kernel assigns uid and gid (from mount superblock).
>>
>> An entry such as this
>>
>> create  cifs.cifs_idmap   *       *               /usr/sbin/cifs.upcall %k
>>
>> is needed in the file /etc/request-key.conf.
>>
>>
>> Signed-off-by: Shirish Pargaonkar <shirishpargaonkar@xxxxxxxxx>
>> ---
>>  Makefile.am   |    2 +-
>>  cifs.upcall.c |   98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 99 insertions(+), 1 deletions(-)
>>
>> diff --git a/Makefile.am b/Makefile.am
>> index 67a0190..c9018ae 100644
>> --- a/Makefile.am
>> +++ b/Makefile.am
>> @@ -11,7 +11,7 @@ man_MANS = mount.cifs.8
>>  if CONFIG_CIFSUPCALL
>>  sbin_PROGRAMS = cifs.upcall
>>  cifs_upcall_SOURCES = cifs.upcall.c data_blob.c asn1.c spnego.c util.c
>> -cifs_upcall_LDADD = -ltalloc -lkeyutils $(KRB5_LDADD)
>> +cifs_upcall_LDADD = -ltalloc -lwbclient -lkeyutils $(KRB5_LDADD)
>>  man_MANS += cifs.upcall.8
>>
>>  #
>> diff --git a/cifs.upcall.c b/cifs.upcall.c
>> index 479517c..fe8a6ad 100644
>> --- a/cifs.upcall.c
>> +++ b/cifs.upcall.c
>> @@ -45,6 +45,13 @@
>>  #include <time.h>
>>  #include <netdb.h>
>>  #include <arpa/inet.h>
>> +#include <stdint.h>
>> +#include <stdbool.h>
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <errno.h>
>> +#include <limits.h>
>> +#include <wbclient.h>
>>
>>  #include "util.h"
>>  #include "replace.h"
>> @@ -695,6 +702,91 @@ static int cifs_resolver(const key_serial_t key, const char *key_descr)
>>       return 0;
>>  }
>>
>> +static int
>> +cifs_sid_resolver(const key_serial_t key, const char *key_descr)
>> +{
>> +     int i;
>> +     uid_t uid = 0;
>> +     gid_t gid = 0;;
>> +     wbcErr rc = 1;
>> +     const char *keyend = key_descr;
>> +     struct wbcDomainSid sid;
>> +     struct passwd *pw;
>> +     struct group *gr;
>> +
>> +     /* skip next 4 ';' delimiters to get to description */
>> +     for (i = 1; i <= 4; ++i) {
>> +             keyend = index(keyend + 1, ';');
>> +             if (!keyend) {
>> +                     syslog(LOG_ERR, "invalid key description: %s",
>> +                            key_descr);
>> +                     return 1;
>> +             }
>> +     }
>> +     keyend++;
>> +
>> +     if (strncmp(keyend, "os", 2) == 0) {
>> +             keyend = index(keyend + 1, ':');
>> +             keyend++;
>> +             rc = wbcStringToSid(keyend, &sid);
>> +             if (rc)
>> +                     syslog(LOG_DEBUG, "O strtosid: %s, rc: %d", keyend, rc);
>> +             else {
>> +                     rc = wbcSidToUid(&sid, &uid);
>> +                     if (rc)
>> +                             syslog(LOG_DEBUG, "SID %s to uid wbc error: %d",
>> +                                             keyend, rc);
>> +             }
>> +             if (rc) {
>> +                     pw = getpwnam("nobody");
>> +                     if (!pw)
>> +                             syslog(LOG_DEBUG, "SID %s to uid pw error: %d",
>> +                                     keyend, rc);
>> +                     else {
>> +                             uid = pw->pw_uid;
>> +                             rc = 0;
>> +                     }
>> +             }
>> +             if (!rc) {
>> +                     rc = keyctl_instantiate(key, &uid, sizeof(uid_t), 0);
>> +                     if (rc)
>> +                             syslog(LOG_ERR, "%s: key inst: %s",
>> +                                     __func__, strerror(errno));
>> +             }
>
>        Instead of all this if then nesting and continual checking for
>        the value of rc, I think it would be easier to follow the logic
>        and maintain this if it instead either did a "goto out" in the
>        error cases or just did a return when it hits an error.

Will comments help?  I thought of using function calls and goto calls
but none of them will make readability and logic any easier.
There are five different calls, and if either of first two fail, insetead of
returning, third one gets called and all calls are different
(e.g. if either of wbcStringToSid or wbcSidToUid, getpwnam should
be called and if either of  wbcStringToSid or wbcSidToGid fail,
getgrnam should be called.
keyctl_instantiate should be called if either  wbcSidToUid or getpwnam
succeed (in that order) or  if either wbcSidToGid or getgrnam succeed
(in that order).
It would not be any clearer to follow this with goto statements.

>
>> +     } else if (strncmp(keyend, "gs", 2) == 0) {
>> +             keyend = index(keyend + 1, ':');
>> +             keyend++;
>> +             rc = wbcStringToSid(keyend, &sid);
>> +             if (rc)
>> +                     syslog(LOG_DEBUG, "O strtosid: %s, rc: %d", keyend, rc);
>> +             else {
>> +                     rc = wbcSidToGid(&sid, &gid);
>> +                     if (rc)
>> +                             syslog(LOG_DEBUG, "SID %s to gid wbc error: %d",
>> +                                             keyend, rc);
>> +             }
>> +             if (rc) {
>> +                     gr = getgrnam("nogroup");
>> +                     if (!gr)
>> +                             syslog(LOG_DEBUG, "SID %s to gid pw error: %d",
>> +                                             keyend, rc);
>> +                     else {
>> +                             gid = gr->gr_gid;
>> +                             rc = 0;
>> +                     }
>> +             }
>> +             if (!rc) {
>> +                     rc = keyctl_instantiate(key, &gid, sizeof(gid_t), 0);
>> +                     if (rc)
>> +                             syslog(LOG_ERR, "%s: key inst: %s",
>> +                                             __func__, strerror(errno));
>> +             }
>> +     } else
>> +             syslog(LOG_DEBUG, "Invalid SID");
>                                  ^^^^^^^^^^^^^^
>                Might be helpful to know what that SID is, don't you
>                think?

yes, will fix this.

>> +
>> +     return rc;
>> +}
>> +
>>  /*
>>   * Older kernels sent IPv6 addresses without colons. Well, at least
>>   * they're fixed-length strings. Convert these addresses to have colon
>> @@ -833,6 +925,12 @@ int main(const int argc, char *const argv[])
>>               goto out;
>>       }
>>
>> +     if ((strncmp(buf, "cifs.cifs_idmap", sizeof("cifs.cifs_idmap") - 1)
>> +                     == 0)) {
>> +             rc = cifs_sid_resolver(key, buf);
>> +             goto out;
>> +     }
>> +
>>       have = decode_key_description(buf, &arg);
>>       SAFE_FREE(buf);
>>       if ((have & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) {
>
>
> --
> Jeff Layton <jlayton@xxxxxxxxxx>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux