client/cifs.spnego.c

ソースコードを見る。

型定義

typedef enum _secType secType_t

列挙型

enum  _secType { KRB5, MS_KRB5 }

関数

int handle_krb5_mech (const char *oid, const char *principal, DATA_BLOB *secblob, DATA_BLOB *sess_key)
int decode_key_description (const char *desc, int *ver, secType_t *sec, char **hostname, uid_t *uid)
int cifs_resolver (const key_serial_t key, const char *key_descr)
int main (const int argc, char *const argv[])

変数

const char * CIFSSPNEGO_VERSION = "1.1"
static const char * prog = "cifs.spnego"


型定義

typedef enum _secType secType_t


列挙型

enum _secType

列挙型の値:
KRB5 
MS_KRB5 

cifs.spnego.c34 行で定義されています。

00034                       {
00035         KRB5,
00036         MS_KRB5
00037 } secType_t;


関数

int handle_krb5_mech ( const char *  oid,
const char *  principal,
DATA_BLOB secblob,
DATA_BLOB sess_key 
)

cifs.spnego.c59 行で定義されています。

参照先 cli_krb5_get_ticket()data_blob_free()gen_negTokenInit()spnego_gen_krb5_wrap().

参照元 main().

00061 {
00062         int retval;
00063         DATA_BLOB tkt, tkt_wrapped;
00064 
00065         /* get a kerberos ticket for the service and extract the session key */
00066         retval = cli_krb5_get_ticket(principal, 0,
00067                                      &tkt, sess_key, 0, NULL, NULL);
00068 
00069         if (retval)
00070                 return retval;
00071 
00072         /* wrap that up in a nice GSS-API wrapping */
00073         tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ);
00074 
00075         /* and wrap that in a shiny SPNEGO wrapper */
00076         *secblob = gen_negTokenInit(OID_KERBEROS5, tkt_wrapped);
00077 
00078         data_blob_free(&tkt_wrapped);
00079         data_blob_free(&tkt);
00080         return retval;
00081 }

int decode_key_description ( const char *  desc,
int *  ver,
secType_t sec,
char **  hostname,
uid_t *  uid 
)

cifs.spnego.c91 行で定義されています。

参照先 errnoindexKRB5lenstrerror()strlcpy().

参照元 main().

00093 {
00094         int retval = 0;
00095         char *pos;
00096         const char *tkn = desc;
00097 
00098         do {
00099                 pos = index(tkn, ';');
00100                 if (strncmp(tkn, "host=", 5) == 0) {
00101                         int len;
00102 
00103                         if (pos == NULL) {
00104                                 len = strlen(tkn);
00105                         } else {
00106                                 len = pos - tkn;
00107                         }
00108                         len -= 4;
00109                         SAFE_FREE(*hostname);
00110                         *hostname = SMB_XMALLOC_ARRAY(char, len);
00111                         strlcpy(*hostname, tkn + 5, len);
00112                         retval |= DKD_HAVE_HOSTNAME;
00113                 } else if (strncmp(tkn, "ipv4=", 5) == 0) {
00114                         /* BB: do we need it if we have hostname already? */
00115                 } else if (strncmp(tkn, "ipv6=", 5) == 0) {
00116                         /* BB: do we need it if we have hostname already? */
00117                 } else if (strncmp(tkn, "sec=", 4) == 0) {
00118                         if (strncmp(tkn + 4, "krb5", 4) == 0) {
00119                                 retval |= DKD_HAVE_SEC;
00120                                 *sec = KRB5;
00121                         }
00122                 } else if (strncmp(tkn, "uid=", 4) == 0) {
00123                         errno = 0;
00124                         *uid = strtol(tkn + 4, NULL, 16);
00125                         if (errno != 0) {
00126                                 syslog(LOG_WARNING, "Invalid uid format: %s",
00127                                        strerror(errno));
00128                                 return 1;
00129                         } else {
00130                                 retval |= DKD_HAVE_UID;
00131                         }
00132                 } else if (strncmp(tkn, "ver=", 4) == 0) {      /* if version */
00133                         errno = 0;
00134                         *ver = strtol(tkn + 4, NULL, 16);
00135                         if (errno != 0) {
00136                                 syslog(LOG_WARNING,
00137                                        "Invalid version format: %s",
00138                                        strerror(errno));
00139                                 return 1;
00140                         } else {
00141                                 retval |= DKD_HAVE_VERSION;
00142                         }
00143                 }
00144                 if (pos == NULL)
00145                         break;
00146                 tkn = pos + 1;
00147         } while (tkn);
00148         return retval;
00149 }

int cifs_resolver ( const key_serial_t  key,
const char *  key_descr 
)

cifs.spnego.c151 行で定義されています。

参照先 cerrnoindexstrerror().

参照元 main().

00152 {
00153         int c;
00154         struct addrinfo *addr;
00155         char ip[INET6_ADDRSTRLEN];
00156         void *p;
00157         const char *keyend = key_descr;
00158         /* skip next 4 ';' delimiters to get to description */
00159         for (c = 1; c <= 4; c++) {
00160                 keyend = index(keyend+1, ';');
00161                 if (!keyend) {
00162                         syslog(LOG_WARNING, "invalid key description: %s",
00163                                         key_descr);
00164                         return 1;
00165                 }
00166         }
00167         keyend++;
00168 
00169         /* resolve name to ip */
00170         c = getaddrinfo(keyend, NULL, NULL, &addr);
00171         if (c) {
00172                 syslog(LOG_WARNING, "unable to resolve hostname: %s [%s]",
00173                                 keyend, gai_strerror(c));
00174                 return 1;
00175         }
00176 
00177         /* conver ip to string form */
00178         if (addr->ai_family == AF_INET) {
00179                 p = &(((struct sockaddr_in *)addr->ai_addr)->sin_addr);
00180         } else {
00181                 p = &(((struct sockaddr_in6 *)addr->ai_addr)->sin6_addr);
00182         }
00183         if (!inet_ntop(addr->ai_family, p, ip, sizeof(ip))) {
00184                 syslog(LOG_WARNING, "%s: inet_ntop: %s",
00185                                 __FUNCTION__, strerror(errno));
00186                 freeaddrinfo(addr);
00187                 return 1;
00188         }
00189 
00190         /* setup key */
00191         c = keyctl_instantiate(key, ip, strlen(ip)+1, 0);
00192         if (c == -1) {
00193                 syslog(LOG_WARNING, "%s: keyctl_instantiate: %s",
00194                                 __FUNCTION__, strerror(errno));
00195                 freeaddrinfo(addr);
00196                 return 1;
00197         }
00198 
00199         freeaddrinfo(addr);
00200         return 0;
00201 }

int main ( const int  argc,
char *const   argv[] 
)

cifs.spnego.c203 行で定義されています。

参照先 bufccifs_resolver()CIFSSPNEGO_VERSIONcifs_spnego_msg::datadata_blob_free()data_blob_nulldecode_key_description()errnofprintf()handle_krb5_mech()KRB5lenoptindprogcifs_spnego_msg::secblob_lenstrerror()strlcpy()cifs_spnego_msg::version.

参照元 parse_quota_set().

00204 {
00205         struct cifs_spnego_msg *keydata = NULL;
00206         DATA_BLOB secblob = data_blob_null;
00207         DATA_BLOB sess_key = data_blob_null;
00208         secType_t sectype;
00209         key_serial_t key;
00210         size_t datalen;
00211         long rc = 1;
00212         uid_t uid;
00213         int kernel_upcall_version;
00214         int c, use_cifs_service_prefix = 0;
00215         char *buf, *hostname = NULL;
00216 
00217         openlog(prog, 0, LOG_DAEMON);
00218         if (argc < 1) {
00219                 syslog(LOG_WARNING, "Usage: %s [-c] key_serial", prog);
00220                 goto out;
00221         }
00222 
00223         while ((c = getopt(argc, argv, "cv")) != -1) {
00224                 switch (c) {
00225                 case 'c':{
00226                         use_cifs_service_prefix = 1;
00227                         break;
00228                         }
00229                 case 'v':{
00230                         syslog(LOG_WARNING, "version: %s", CIFSSPNEGO_VERSION);
00231                         fprintf(stderr, "version: %s", CIFSSPNEGO_VERSION);
00232                         break;
00233                         }
00234                 default:{
00235                         syslog(LOG_WARNING, "unknow option: %c", c);
00236                         goto out;
00237                         }
00238                 }
00239         }
00240         /* get key and keyring values */
00241         errno = 0;
00242         key = strtol(argv[optind], NULL, 10);
00243         if (errno != 0) {
00244                 syslog(LOG_WARNING, "Invalid key format: %s", strerror(errno));
00245                 goto out;
00246         }
00247 
00248         rc = keyctl_describe_alloc(key, &buf);
00249         if (rc == -1) {
00250                 syslog(LOG_WARNING, "keyctl_describe_alloc failed: %s",
00251                        strerror(errno));
00252                 rc = 1;
00253                 goto out;
00254         }
00255 
00256         if (strncmp(buf, "cifs.resolver", sizeof("cifs.resolver")-1) == 0) {
00257                 rc = cifs_resolver(key, buf);
00258                 goto out;
00259         }
00260 
00261         rc = decode_key_description(buf, &kernel_upcall_version, &sectype,
00262                                     &hostname, &uid);
00263         if ((rc & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) {
00264                 syslog(LOG_WARNING,
00265                        "unable to get from description necessary params");
00266                 rc = 1;
00267                 SAFE_FREE(buf);
00268                 goto out;
00269         }
00270         SAFE_FREE(buf);
00271 
00272         if (kernel_upcall_version != CIFS_SPNEGO_UPCALL_VERSION) {
00273                 syslog(LOG_WARNING,
00274                        "incompatible kernel upcall version: 0x%x",
00275                        kernel_upcall_version);
00276                 rc = 1;
00277                 goto out;
00278         }
00279 
00280         if (rc & DKD_HAVE_UID) {
00281                 rc = setuid(uid);
00282                 if (rc == -1) {
00283                         syslog(LOG_WARNING, "setuid: %s", strerror(errno));
00284                         goto out;
00285                 }
00286         }
00287 
00288         /* BB: someday upcall SPNEGO blob could be checked here to decide
00289          * what mech to use */
00290 
00291         // do mech specific authorization
00292         switch (sectype) {
00293         case KRB5:{
00294                         char *princ;
00295                         size_t len;
00296 
00297                         /* for "cifs/" service name + terminating 0 */
00298                         len = strlen(hostname) + 5 + 1;
00299                         princ = SMB_XMALLOC_ARRAY(char, len);
00300                         if (!princ) {
00301                                 rc = 1;
00302                                 break;
00303                         }
00304                         if (use_cifs_service_prefix) {
00305                                 strlcpy(princ, "cifs/", len);
00306                         } else {
00307                                 strlcpy(princ, "host/", len);
00308                         }
00309                         strlcpy(princ + 5, hostname, len - 5);
00310 
00311                         rc = handle_krb5_mech(OID_KERBEROS5, princ,
00312                                               &secblob, &sess_key);
00313                         SAFE_FREE(princ);
00314                         break;
00315                 }
00316         default:{
00317                         syslog(LOG_WARNING, "sectype: %d is not implemented",
00318                                sectype);
00319                         rc = 1;
00320                         break;
00321                 }
00322         }
00323 
00324         if (rc) {
00325                 goto out;
00326         }
00327 
00328         /* pack SecurityBLob and SessionKey into downcall packet */
00329         datalen =
00330             sizeof(struct cifs_spnego_msg) + secblob.length + sess_key.length;
00331         keydata = (struct cifs_spnego_msg*)SMB_XMALLOC_ARRAY(char, datalen);
00332         if (!keydata) {
00333                 rc = 1;
00334                 goto out;
00335         }
00336         keydata->version = CIFS_SPNEGO_UPCALL_VERSION;
00337         keydata->flags = 0;
00338         keydata->sesskey_len = sess_key.length;
00339         keydata->secblob_len = secblob.length;
00340         memcpy(&(keydata->data), sess_key.data, sess_key.length);
00341         memcpy(&(keydata->data) + keydata->sesskey_len,
00342                secblob.data, secblob.length);
00343 
00344         /* setup key */
00345         rc = keyctl_instantiate(key, keydata, datalen, 0);
00346         if (rc == -1) {
00347                 syslog(LOG_WARNING, "keyctl_instantiate: %s", strerror(errno));
00348                 goto out;
00349         }
00350 
00351         /* BB: maybe we need use timeout for key: for example no more then
00352          * ticket lifietime? */
00353         /* keyctl_set_timeout( key, 60); */
00354       out:
00355         data_blob_free(&secblob);
00356         data_blob_free(&sess_key);
00357         SAFE_FREE(hostname);
00358         SAFE_FREE(keydata);
00359         return rc;
00360 }


変数

const char* CIFSSPNEGO_VERSION = "1.1"

cifs.spnego.c32 行で定義されています。

参照元 main().

const char* prog = "cifs.spnego" [static]

cifs.spnego.c33 行で定義されています。

参照元 main()usage().


Sambaに対してSat Aug 29 21:23:31 2009に生成されました。  doxygen 1.4.7