diff options
-rw-r--r-- | client/cifs.upcall.c | 63 |
1 files changed, 33 insertions, 30 deletions
diff --git a/client/cifs.upcall.c b/client/cifs.upcall.c index 926ec2064d..0ddcc75660 100644 --- a/client/cifs.upcall.c +++ b/client/cifs.upcall.c @@ -32,11 +32,11 @@ create dns_resolver * * /usr/local/sbin/cifs.upcall %k const char *CIFSSPNEGO_VERSION = "1.2"; static const char *prog = "cifs.upcall"; -typedef enum _secType { +typedef enum _sectype { NONE = 0, KRB5, MS_KRB5 -} secType_t; +} sectype_t; /* * given a process ID, get the value of the KRB5CCNAME environment variable @@ -156,9 +156,16 @@ handle_krb5_mech(const char *oid, const char *principal, DATA_BLOB *secblob, #define DKD_HAVE_PID 0x40 #define DKD_MUSTHAVE_SET (DKD_HAVE_HOSTNAME|DKD_HAVE_VERSION|DKD_HAVE_SEC) +static struct decoded_args { + int ver; + char *hostname; + uid_t uid; + pid_t pid; + sectype_t sec; +}; + static int -decode_key_description(const char *desc, int *ver, secType_t *sec, - char **hostname, uid_t *uid, pid_t *pid) +decode_key_description(const char *desc, struct decoded_args *arg) { int retval = 0; char *pos; @@ -175,9 +182,9 @@ decode_key_description(const char *desc, int *ver, secType_t *sec, len = pos - tkn; len -= 4; - SAFE_FREE(*hostname); - *hostname = SMB_XMALLOC_ARRAY(char, len); - strlcpy(*hostname, tkn + 5, len); + SAFE_FREE(arg->hostname); + arg->hostname = SMB_XMALLOC_ARRAY(char, len); + strlcpy(arg->hostname, tkn + 5, len); retval |= DKD_HAVE_HOSTNAME; } else if (strncmp(tkn, "ipv4=", 5) == 0) { /* BB: do we need it if we have hostname already? */ @@ -185,7 +192,7 @@ decode_key_description(const char *desc, int *ver, secType_t *sec, /* BB: do we need it if we have hostname already? */ } else if (strncmp(tkn, "pid=", 4) == 0) { errno = 0; - *pid = strtol(tkn + 4, NULL, 0); + arg->pid = strtol(tkn + 4, NULL, 0); if (errno != 0) { syslog(LOG_ERR, "Invalid pid format: %s", strerror(errno)); @@ -196,14 +203,14 @@ decode_key_description(const char *desc, int *ver, secType_t *sec, } else if (strncmp(tkn, "sec=", 4) == 0) { if (strncmp(tkn + 4, "krb5", 4) == 0) { retval |= DKD_HAVE_SEC; - *sec = KRB5; + arg->sec = KRB5; } else if (strncmp(tkn + 4, "mskrb5", 6) == 0) { retval |= DKD_HAVE_SEC; - *sec = MS_KRB5; + arg->sec = MS_KRB5; } } else if (strncmp(tkn, "uid=", 4) == 0) { errno = 0; - *uid = strtol(tkn + 4, NULL, 16); + arg->uid = strtol(tkn + 4, NULL, 16); if (errno != 0) { syslog(LOG_ERR, "Invalid uid format: %s", strerror(errno)); @@ -213,7 +220,7 @@ decode_key_description(const char *desc, int *ver, secType_t *sec, } } else if (strncmp(tkn, "ver=", 4) == 0) { /* if version */ errno = 0; - *ver = strtol(tkn + 4, NULL, 16); + arg->ver = strtol(tkn + 4, NULL, 16); if (errno != 0) { syslog(LOG_ERR, "Invalid version format: %s", strerror(errno)); @@ -293,15 +300,12 @@ int main(const int argc, char *const argv[]) struct cifs_spnego_msg *keydata = NULL; DATA_BLOB secblob = data_blob_null; DATA_BLOB sess_key = data_blob_null; - secType_t sectype = NONE; key_serial_t key = 0; size_t datalen; long rc = 1; - uid_t uid = 0; - pid_t pid = 0; - int kernel_upcall_version = 0; int c, use_cifs_service_prefix = 0; - char *buf, *princ, *ccname = NULL, *hostname = NULL; + char *buf, *princ, *ccname = NULL; + struct decoded_args arg = { }; const char *oid; openlog(prog, 0, LOG_DAEMON); @@ -351,8 +355,7 @@ int main(const int argc, char *const argv[]) goto out; } - rc = decode_key_description(buf, &kernel_upcall_version, §ype, - &hostname, &uid, &pid); + rc = decode_key_description(buf, &arg); if ((rc & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) { syslog(LOG_ERR, "unable to get necessary params from key " "description (0x%x)", rc); @@ -362,18 +365,18 @@ int main(const int argc, char *const argv[]) } SAFE_FREE(buf); - if (kernel_upcall_version > CIFS_SPNEGO_UPCALL_VERSION) { + if (arg.ver > CIFS_SPNEGO_UPCALL_VERSION) { syslog(LOG_ERR, "incompatible kernel upcall version: 0x%x", - kernel_upcall_version); + arg.ver); rc = 1; goto out; } if (rc & DKD_HAVE_PID) - ccname = get_krb5_ccname(pid); + ccname = get_krb5_ccname(arg.pid); if (rc & DKD_HAVE_UID) { - rc = setuid(uid); + rc = setuid(arg.uid); if (rc == -1) { syslog(LOG_ERR, "setuid: %s", strerror(errno)); goto out; @@ -381,11 +384,11 @@ int main(const int argc, char *const argv[]) } // do mech specific authorization - switch (sectype) { + switch (arg.sec) { case MS_KRB5: case KRB5: /* for "cifs/" service name + terminating 0 */ - datalen = strlen(hostname) + 5 + 1; + datalen = strlen(arg.hostname) + 5 + 1; princ = SMB_XMALLOC_ARRAY(char, datalen); if (!princ) { rc = 1; @@ -397,9 +400,9 @@ int main(const int argc, char *const argv[]) else strlcpy(princ, "host/", datalen); - strlcpy(princ + 5, hostname, datalen - 5); + strlcpy(princ + 5, arg.hostname, datalen - 5); - if (sectype == MS_KRB5) + if (arg.sec == MS_KRB5) oid = OID_KERBEROS5_OLD; else oid = OID_KERBEROS5; @@ -408,7 +411,7 @@ int main(const int argc, char *const argv[]) SAFE_FREE(princ); break; default: - syslog(LOG_ERR, "sectype: %d is not implemented", sectype); + syslog(LOG_ERR, "sectype: %d is not implemented", arg.sec); rc = 1; break; } @@ -424,7 +427,7 @@ int main(const int argc, char *const argv[]) rc = 1; goto out; } - keydata->version = kernel_upcall_version; + keydata->version = arg.ver; keydata->flags = 0; keydata->sesskey_len = sess_key.length; keydata->secblob_len = secblob.length; @@ -453,7 +456,7 @@ out: data_blob_free(&secblob); data_blob_free(&sess_key); SAFE_FREE(ccname); - SAFE_FREE(hostname); + SAFE_FREE(arg.hostname); SAFE_FREE(keydata); return rc; } |