型定義 | |
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) |
void | usage (void) |
int | main (const int argc, char *const argv[]) |
変数 | |
const char * | CIFSSPNEGO_VERSION = "1.2" |
static const char * | prog = "cifs.upcall" |
const DATA_BLOB | data_blob_null = { NULL, 0, NULL } |
enum _secType |
int handle_krb5_mech | ( | const char * | oid, | |
const char * | principal, | |||
DATA_BLOB * | secblob, | |||
DATA_BLOB * | sess_key | |||
) |
cifs.upcall.c の 60 行で定義されています。
参照先 cli_krb5_get_ticket()・data_blob_free()・gen_negTokenInit()・spnego_gen_krb5_wrap().
00062 { 00063 int retval; 00064 DATA_BLOB tkt, tkt_wrapped; 00065 00066 /* get a kerberos ticket for the service and extract the session key */ 00067 retval = cli_krb5_get_ticket(principal, 0, 00068 &tkt, sess_key, 0, NULL, NULL); 00069 00070 if (retval) 00071 return retval; 00072 00073 /* wrap that up in a nice GSS-API wrapping */ 00074 tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ); 00075 00076 /* and wrap that in a shiny SPNEGO wrapper */ 00077 *secblob = gen_negTokenInit(oid, tkt_wrapped); 00078 00079 data_blob_free(&tkt_wrapped); 00080 data_blob_free(&tkt); 00081 return retval; 00082 }
int decode_key_description | ( | const char * | desc, | |
int * | ver, | |||
secType_t * | sec, | |||
char ** | hostname, | |||
uid_t * | uid | |||
) |
cifs.upcall.c の 92 行で定義されています。
参照先 errno・index・KRB5・len・MS_KRB5・strerror()・strlcpy().
00094 { 00095 int retval = 0; 00096 char *pos; 00097 const char *tkn = desc; 00098 00099 do { 00100 pos = index(tkn, ';'); 00101 if (strncmp(tkn, "host=", 5) == 0) { 00102 int len; 00103 00104 if (pos == NULL) { 00105 len = strlen(tkn); 00106 } else { 00107 len = pos - tkn; 00108 } 00109 len -= 4; 00110 SAFE_FREE(*hostname); 00111 *hostname = SMB_XMALLOC_ARRAY(char, len); 00112 strlcpy(*hostname, tkn + 5, len); 00113 retval |= DKD_HAVE_HOSTNAME; 00114 } else if (strncmp(tkn, "ipv4=", 5) == 0) { 00115 /* BB: do we need it if we have hostname already? */ 00116 } else if (strncmp(tkn, "ipv6=", 5) == 0) { 00117 /* BB: do we need it if we have hostname already? */ 00118 } else if (strncmp(tkn, "sec=", 4) == 0) { 00119 if (strncmp(tkn + 4, "krb5", 4) == 0) { 00120 retval |= DKD_HAVE_SEC; 00121 *sec = KRB5; 00122 } else if (strncmp(tkn + 4, "mskrb5", 6) == 0) { 00123 retval |= DKD_HAVE_SEC; 00124 *sec = MS_KRB5; 00125 } 00126 } else if (strncmp(tkn, "uid=", 4) == 0) { 00127 errno = 0; 00128 *uid = strtol(tkn + 4, NULL, 16); 00129 if (errno != 0) { 00130 syslog(LOG_WARNING, "Invalid uid format: %s", 00131 strerror(errno)); 00132 return 1; 00133 } else { 00134 retval |= DKD_HAVE_UID; 00135 } 00136 } else if (strncmp(tkn, "ver=", 4) == 0) { /* if version */ 00137 errno = 0; 00138 *ver = strtol(tkn + 4, NULL, 16); 00139 if (errno != 0) { 00140 syslog(LOG_WARNING, 00141 "Invalid version format: %s", 00142 strerror(errno)); 00143 return 1; 00144 } else { 00145 retval |= DKD_HAVE_VERSION; 00146 } 00147 } 00148 if (pos == NULL) 00149 break; 00150 tkn = pos + 1; 00151 } while (tkn); 00152 return retval; 00153 }
int cifs_resolver | ( | const key_serial_t | key, | |
const char * | key_descr | |||
) |
cifs.upcall.c の 155 行で定義されています。
参照先 c・errno・index・strerror().
00156 { 00157 int c; 00158 struct addrinfo *addr; 00159 char ip[INET6_ADDRSTRLEN]; 00160 void *p; 00161 const char *keyend = key_descr; 00162 /* skip next 4 ';' delimiters to get to description */ 00163 for (c = 1; c <= 4; c++) { 00164 keyend = index(keyend+1, ';'); 00165 if (!keyend) { 00166 syslog(LOG_WARNING, "invalid key description: %s", 00167 key_descr); 00168 return 1; 00169 } 00170 } 00171 keyend++; 00172 00173 /* resolve name to ip */ 00174 c = getaddrinfo(keyend, NULL, NULL, &addr); 00175 if (c) { 00176 syslog(LOG_WARNING, "unable to resolve hostname: %s [%s]", 00177 keyend, gai_strerror(c)); 00178 return 1; 00179 } 00180 00181 /* conver ip to string form */ 00182 if (addr->ai_family == AF_INET) { 00183 p = &(((struct sockaddr_in *)addr->ai_addr)->sin_addr); 00184 } else { 00185 p = &(((struct sockaddr_in6 *)addr->ai_addr)->sin6_addr); 00186 } 00187 if (!inet_ntop(addr->ai_family, p, ip, sizeof(ip))) { 00188 syslog(LOG_WARNING, "%s: inet_ntop: %s", 00189 __FUNCTION__, strerror(errno)); 00190 freeaddrinfo(addr); 00191 return 1; 00192 } 00193 00194 /* setup key */ 00195 c = keyctl_instantiate(key, ip, strlen(ip)+1, 0); 00196 if (c == -1) { 00197 syslog(LOG_WARNING, "%s: keyctl_instantiate: %s", 00198 __FUNCTION__, strerror(errno)); 00199 freeaddrinfo(addr); 00200 return 1; 00201 } 00202 00203 freeaddrinfo(addr); 00204 return 0; 00205 }
static void usage | ( | void | ) |
cifs.upcall.c の 208 行で定義されています。
参照元 check_pac_checksum()・do_connection()・main()・parse_mount_smb()・process_nonroot()・process_options()・process_root().
00209 { 00210 syslog(LOG_WARNING, "Usage: %s [-c] [-v] key_serial", prog); 00211 fprintf(stderr, "Usage: %s [-c] [-v] key_serial\n", prog); 00212 }
int main | ( | const int | argc, | |
char *const | argv[] | |||
) |
cifs.upcall.c の 214 行で定義されています。
参照先 buf・c・cifs_resolver()・CIFSSPNEGO_VERSION・cifs_spnego_msg::data・data_blob_free()・data_blob_null・decode_key_description()・errno・handle_krb5_mech()・KRB5・len・MS_KRB5・optind・printf()・prog・cifs_spnego_msg::secblob_len・strerror()・strlcpy()・usage()・cifs_spnego_msg::version.
00215 { 00216 struct cifs_spnego_msg *keydata = NULL; 00217 DATA_BLOB secblob = data_blob_null; 00218 DATA_BLOB sess_key = data_blob_null; 00219 secType_t sectype; 00220 key_serial_t key = 0; 00221 size_t datalen; 00222 long rc = 1; 00223 uid_t uid; 00224 int kernel_upcall_version; 00225 int c, use_cifs_service_prefix = 0; 00226 char *buf, *hostname = NULL; 00227 const char *oid; 00228 00229 openlog(prog, 0, LOG_DAEMON); 00230 00231 while ((c = getopt(argc, argv, "cv")) != -1) { 00232 switch (c) { 00233 case 'c':{ 00234 use_cifs_service_prefix = 1; 00235 break; 00236 } 00237 case 'v':{ 00238 printf("version: %s\n", CIFSSPNEGO_VERSION); 00239 goto out; 00240 } 00241 default:{ 00242 syslog(LOG_WARNING, "unknown option: %c", c); 00243 goto out; 00244 } 00245 } 00246 } 00247 00248 /* is there a key? */ 00249 if (argc <= optind) { 00250 usage(); 00251 goto out; 00252 } 00253 00254 /* get key and keyring values */ 00255 errno = 0; 00256 key = strtol(argv[optind], NULL, 10); 00257 if (errno != 0) { 00258 key = 0; 00259 syslog(LOG_WARNING, "Invalid key format: %s", strerror(errno)); 00260 goto out; 00261 } 00262 00263 rc = keyctl_describe_alloc(key, &buf); 00264 if (rc == -1) { 00265 syslog(LOG_WARNING, "keyctl_describe_alloc failed: %s", 00266 strerror(errno)); 00267 rc = 1; 00268 goto out; 00269 } 00270 00271 if ((strncmp(buf, "cifs.resolver", sizeof("cifs.resolver")-1) == 0) || 00272 (strncmp(buf, "dns_resolver", sizeof("dns_resolver")-1) == 0)) { 00273 rc = cifs_resolver(key, buf); 00274 goto out; 00275 } 00276 00277 rc = decode_key_description(buf, &kernel_upcall_version, §ype, 00278 &hostname, &uid); 00279 if ((rc & DKD_MUSTHAVE_SET) != DKD_MUSTHAVE_SET) { 00280 syslog(LOG_WARNING, 00281 "unable to get from description necessary params"); 00282 rc = 1; 00283 SAFE_FREE(buf); 00284 goto out; 00285 } 00286 SAFE_FREE(buf); 00287 00288 if (kernel_upcall_version > CIFS_SPNEGO_UPCALL_VERSION) { 00289 syslog(LOG_WARNING, 00290 "incompatible kernel upcall version: 0x%x", 00291 kernel_upcall_version); 00292 rc = 1; 00293 goto out; 00294 } 00295 00296 if (rc & DKD_HAVE_UID) { 00297 rc = setuid(uid); 00298 if (rc == -1) { 00299 syslog(LOG_WARNING, "setuid: %s", strerror(errno)); 00300 goto out; 00301 } 00302 } 00303 00304 /* BB: someday upcall SPNEGO blob could be checked here to decide 00305 * what mech to use */ 00306 00307 // do mech specific authorization 00308 switch (sectype) { 00309 case MS_KRB5: 00310 case KRB5:{ 00311 char *princ; 00312 size_t len; 00313 00314 /* for "cifs/" service name + terminating 0 */ 00315 len = strlen(hostname) + 5 + 1; 00316 princ = SMB_XMALLOC_ARRAY(char, len); 00317 if (!princ) { 00318 rc = 1; 00319 break; 00320 } 00321 if (use_cifs_service_prefix) { 00322 strlcpy(princ, "cifs/", len); 00323 } else { 00324 strlcpy(princ, "host/", len); 00325 } 00326 strlcpy(princ + 5, hostname, len - 5); 00327 00328 if (sectype == MS_KRB5) 00329 oid = OID_KERBEROS5_OLD; 00330 else 00331 oid = OID_KERBEROS5; 00332 00333 rc = handle_krb5_mech(oid, princ, &secblob, &sess_key); 00334 SAFE_FREE(princ); 00335 break; 00336 } 00337 default:{ 00338 syslog(LOG_WARNING, "sectype: %d is not implemented", 00339 sectype); 00340 rc = 1; 00341 break; 00342 } 00343 } 00344 00345 if (rc) { 00346 goto out; 00347 } 00348 00349 /* pack SecurityBLob and SessionKey into downcall packet */ 00350 datalen = 00351 sizeof(struct cifs_spnego_msg) + secblob.length + sess_key.length; 00352 keydata = (struct cifs_spnego_msg*)SMB_XMALLOC_ARRAY(char, datalen); 00353 if (!keydata) { 00354 rc = 1; 00355 goto out; 00356 } 00357 keydata->version = kernel_upcall_version; 00358 keydata->flags = 0; 00359 keydata->sesskey_len = sess_key.length; 00360 keydata->secblob_len = secblob.length; 00361 memcpy(&(keydata->data), sess_key.data, sess_key.length); 00362 memcpy(&(keydata->data) + keydata->sesskey_len, 00363 secblob.data, secblob.length); 00364 00365 /* setup key */ 00366 rc = keyctl_instantiate(key, keydata, datalen, 0); 00367 if (rc == -1) { 00368 syslog(LOG_WARNING, "keyctl_instantiate: %s", strerror(errno)); 00369 goto out; 00370 } 00371 00372 /* BB: maybe we need use timeout for key: for example no more then 00373 * ticket lifietime? */ 00374 /* keyctl_set_timeout( key, 60); */ 00375 out: 00376 /* 00377 * on error, negatively instantiate the key ourselves so that we can 00378 * make sure the kernel doesn't hang it off of a searchable keyring 00379 * and interfere with the next attempt to instantiate the key. 00380 */ 00381 if (rc != 0 && key == 0) 00382 keyctl_negate(key, 1, KEY_REQKEY_DEFL_DEFAULT); 00383 data_blob_free(&secblob); 00384 data_blob_free(&sess_key); 00385 SAFE_FREE(hostname); 00386 SAFE_FREE(keydata); 00387 return rc; 00388 }
const char* CIFSSPNEGO_VERSION = "1.2" |
cifs.upcall.c の 32 行で定義されています。
const char* prog = "cifs.upcall" [static] |
cifs.upcall.c の 33 行で定義されています。
const DATA_BLOB data_blob_null = { NULL, 0, NULL } |