From: Chaskiel Grundman Date: Sun, 28 Apr 2013 18:27:47 +0000 (-0400) Subject: Krb5 ticket support for server-to-server and localauth X-Git-Tag: upstream/1.8.0_pre1^2~1062^2~4 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=7ac5dddbfd439e5276ae5bea00ea22cd1b5897d3;p=packages%2Fo%2Fopenafs.git Krb5 ticket support for server-to-server and localauth Create a tkt_MakeTicket5 that creates a native krb5 rxkad token with a service key supported by the rfc3961 library (session keys must be provided as DES) Update GenericAuth to search for rxkad_krb5 keys and call tkt_MakeTicket5 if it finds any. Change-Id: Ia9543fdcffcbf3ca899a003908662ff3daa8ee07 --- diff --git a/src/auth/authcon.c b/src/auth/authcon.c index 8976947ba..fe54bfd7d 100644 --- a/src/auth/authcon.c +++ b/src/auth/authcon.c @@ -19,6 +19,7 @@ #define HC_DEPRECATED #include +#include #include #include @@ -98,35 +99,72 @@ GenericAuth(struct afsconf_dir *adir, afs_int32 *aindex, rxkad_level enclevel) { - char tbuffer[256]; +#ifdef UKERNEL + return QuickAuth(astr, aindex); +#else + int enctype_preflist[]={18, 17, 23, 16, 0}; + char tbuffer[512]; struct ktc_encryptionKey key, session; struct rx_securityClass *tclass; afs_int32 kvno; afs_int32 ticketLen; afs_int32 code; + int use_krb5=0; + struct afsconf_typedKey *kobj; + struct rx_opaque *keymat; + int *et; /* first, find the right key and kvno to use */ - code = afsconf_GetLatestKey(adir, &kvno, &key); - if (code) { - return QuickAuth(astr, aindex); + + et = enctype_preflist; + while(*et != 0) { + code = afsconf_GetLatestKeyByTypes(adir, afsconf_rxkad_krb5, *et, + &kobj); + if (code == 0) { + afsconf_keyType tktype; + int tenctype; + afsconf_typedKey_values(kobj, &tktype, &kvno, &tenctype, &keymat); + RAND_add(keymat->val, keymat->len, 0.0); + use_krb5 = 1; + break; + } + et++; } - /* next create random session key, using key for seed to good random */ - DES_init_random_number_generator((DES_cblock *) &key); + if (use_krb5 == 0) { + code = afsconf_GetLatestKey(adir, &kvno, &key); + if (code) { + return QuickAuth(astr, aindex); + } + /* next create random session key, using key for seed to good random */ + DES_init_random_number_generator((DES_cblock *) &key); + } code = DES_new_random_key((DES_cblock *) &session); if (code) { + if (use_krb5) + afsconf_typedKey_put(&kobj); return QuickAuth(astr, aindex); } - /* now create the actual ticket */ - ticketLen = sizeof(tbuffer); - memset(tbuffer, '\0', sizeof(tbuffer)); - code = - tkt_MakeTicket(tbuffer, &ticketLen, &key, AUTH_SUPERUSER, "", "", 0, - 0xffffffff, &session, 0, "afs", ""); - /* parms were buffer, ticketlen, key to seal ticket with, principal - * name, instance and cell, start time, end time, session key to seal - * in ticket, inet host, server name and server instance */ + if (use_krb5) { + ticketLen = sizeof(tbuffer); + memset(tbuffer, '\0', sizeof(tbuffer)); + code = + tkt_MakeTicket5(tbuffer, &ticketLen, *et, &kvno, keymat->val, + keymat->len, AUTH_SUPERUSER, "", "", 0, 0x7fffffff, + &session, "afs", ""); + afsconf_typedKey_put(&kobj); + } else { + /* now create the actual ticket */ + ticketLen = sizeof(tbuffer); + memset(tbuffer, '\0', sizeof(tbuffer)); + code = + tkt_MakeTicket(tbuffer, &ticketLen, &key, AUTH_SUPERUSER, "", "", 0, + 0xffffffff, &session, 0, "afs", ""); + /* parms were buffer, ticketlen, key to seal ticket with, principal + * name, instance and cell, start time, end time, session key to seal + * in ticket, inet host, server name and server instance */ + } if (code) { return QuickAuth(astr, aindex); } @@ -141,6 +179,7 @@ GenericAuth(struct afsconf_dir *adir, *astr = tclass; *aindex = RX_SECIDX_KAD; return 0; +#endif } /* build a fake ticket for 'afs' using keys from adir, returning an diff --git a/src/libafsrpc/afsrpc.def b/src/libafsrpc/afsrpc.def index 5d226691c..5772ad0ea 100755 --- a/src/libafsrpc/afsrpc.def +++ b/src/libafsrpc/afsrpc.def @@ -341,6 +341,7 @@ EXPORTS rx_GetNetworkError @346 afs_set_com_err_hook @347 rxkad_NewKrb5ServerSecurityObject @348 + tkt_MakeTicket5 @349 ; for performance testing rx_TSFPQGlobSize @2001 DATA diff --git a/src/libafsrpc/libafsrpc.la.sym b/src/libafsrpc/libafsrpc.la.sym index b5c05713f..d1b9c4608 100644 --- a/src/libafsrpc/libafsrpc.la.sym +++ b/src/libafsrpc/libafsrpc.la.sym @@ -165,6 +165,7 @@ time_to_life tkt_CheckTimes tkt_DecodeTicket tkt_MakeTicket +tkt_MakeTicket5 xdr_afsUUID xdr_afs_int32 xdr_afs_int64 diff --git a/src/rxkad/liboafs_rxkad.la.sym b/src/rxkad/liboafs_rxkad.la.sym index acf9f3c2c..4933f9b28 100644 --- a/src/rxkad/liboafs_rxkad.la.sym +++ b/src/rxkad/liboafs_rxkad.la.sym @@ -7,3 +7,4 @@ rxkad_NewServerSecurityObject time_to_life tkt_CheckTimes tkt_MakeTicket +tkt_MakeTicket5 diff --git a/src/rxkad/rxkad_prototypes.h b/src/rxkad/rxkad_prototypes.h index e73f1d1a2..525b9d9af 100644 --- a/src/rxkad/rxkad_prototypes.h +++ b/src/rxkad/rxkad_prototypes.h @@ -162,5 +162,10 @@ extern int tkt_DecodeTicket5(char *ticket, afs_int32 ticket_len, char *inst, char *cell, struct ktc_encryptionKey *session_key, afs_int32 * host, afs_uint32 * start, afs_uint32 * end, afs_int32 disableDotCheck); +extern int tkt_MakeTicket5(char *ticket, int *ticketLen, int enctype, int *kvno, + void *key, size_t keylen, + char *name, char *inst, char *cell, afs_uint32 start, + afs_uint32 end, struct ktc_encryptionKey *sessionKey, + char *sname, char *sinst); #endif diff --git a/src/rxkad/ticket5.c b/src/rxkad/ticket5.c index 5ce4c7a94..1dad81a65 100644 --- a/src/rxkad/ticket5.c +++ b/src/rxkad/ticket5.c @@ -536,3 +536,99 @@ krb5_des_decrypt(struct ktc_encryptionKey *key, int etype, void *in, return ret; } + + +int +tkt_MakeTicket5(char *ticket, int *ticketLen, int enctype, int *kvno, + void *key, size_t keylen, + char *name, char *inst, char *cell, afs_uint32 start, + afs_uint32 end, struct ktc_encryptionKey *sessionKey, + char *sname, char *sinst) +{ + EncTicketPart data; + EncryptedData encdata; + char *buf, *encodebuf; + size_t encodelen, allocsiz; + heim_general_string carray[2]; + int code; + krb5_context context; + krb5_keyblock kb; + krb5_crypto cr; + krb5_data encrypted; + size_t tl; + + memset(&encrypted, 0, sizeof(encrypted)); + cr = NULL; + context = NULL; + buf = NULL; + memset(&kb, 0, sizeof(kb)); + memset(&data, 0, sizeof(data)); + + data.flags.transited_policy_checked = 1; + data.key.keytype=ETYPE_DES_CBC_CRC; + data.key.keyvalue.data=sessionKey->data; + data.key.keyvalue.length=8; + data.crealm=cell; + carray[0]=name; + carray[1]=inst; + data.cname.name_type=KRB5_NT_PRINCIPAL; + data.cname.name_string.val=carray; + data.cname.name_string.len=inst[0]?2:1; + data.authtime=start; + data.endtime=end; + + allocsiz = length_EncTicketPart(&data); + buf = rxi_Alloc(allocsiz); + encodelen = allocsiz; + /* encode function wants pointer to end of buffer */ + encodebuf = buf + allocsiz - 1; + code = encode_EncTicketPart(encodebuf, allocsiz, &data, &encodelen); + + if (code) + goto cleanup; + code = krb5_init_context(&context); + if (code) + goto cleanup; + code = krb5_keyblock_init(context, enctype, key, keylen, &kb); + if (code) + goto cleanup; + code = krb5_crypto_init(context, &kb, enctype, &cr); + if (code) + goto cleanup; + code = krb5_encrypt(context, cr, KRB5_KU_TICKET, buf, + encodelen, &encrypted); + if (code) + goto cleanup; + memset(&encdata, 0, sizeof(encdata)); + encdata.etype=enctype; + encdata.kvno=kvno; + encdata.cipher.data=encrypted.data; + encdata.cipher.length=encrypted.length; + + if (length_EncryptedData(&encdata) > *ticketLen) { + code = RXKADTICKETLEN; + goto cleanup; + } + tl=*ticketLen; + code = encode_EncryptedData(ticket + *ticketLen - 1, *ticketLen, &encdata, &tl); + if (code == 0) { + *kvno=RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY; + /* + * encode function fills in from the end. move data to + * beginning of buffer + */ + memmove(ticket, ticket + *ticketLen - tl, tl); + *ticketLen=tl; + } + +cleanup: + krb5_data_free(&encrypted); + if (cr != NULL) + krb5_crypto_destroy(context, cr); + krb5_free_keyblock_contents(context, &kb); + krb5_free_context(context); + rxi_Free(buf, allocsiz); + if ((code && 0xFFFFFF00) == ERROR_TABLE_BASE_asn1) + return RXKADINCONSISTENCY; + return code; +}