Code_t Z_MakeZcodeAuthentication(register ZNotice_t *notice, char *buffer, int buffer_len, int *phdr_len, krb5_creds *creds) { krb5_error_code result = 0; krb5_keyblock *keyblock; krb5_auth_context authctx; krb5_data *authent; char *cksum_start, *cstart, *cend; int cksum_len, zcode_len = 0, phdr_adj = 0; notice->z_ascii_authent = NULL; keyblock = Z_credskey(creds); authent = (krb5_data *)malloc(sizeof(krb5_data)); if (authent == NULL) result = ENOMEM; authent->data = NULL; /* so that we can blithely krb5_fre_data_contents on the way out */ if (!result) result = krb5_auth_con_init(Z_krb5_ctx, &authctx); if (!result) { result = krb5_mk_req_extended(Z_krb5_ctx, &authctx, 0 /* options */, 0 /* in_data */, creds, authent); krb5_auth_con_free(Z_krb5_ctx, authctx); } if (!result || result == KRB5KRB_AP_ERR_TKT_EXPIRED) { notice->z_auth = 1; if (result == 0) { notice->z_authent_len = authent->length; } else { notice->z_authent_len = 0; result = 0; } zcode_len = notice->z_authent_len * 2 + 2; /* 2x growth plus Z and null */ notice->z_ascii_authent = (char *)malloc(zcode_len); if (notice->z_ascii_authent == NULL) result = ENOMEM; } if (!result) result = ZMakeZcode(notice->z_ascii_authent, zcode_len, (unsigned char *)authent->data, notice->z_authent_len); /* format the notice header, with a zero checksum */ if (!result) result = Z_NewFormatRawHeader(notice, buffer, buffer_len, phdr_len, &cksum_start, &cksum_len, &cstart, &cend); notice->z_authent_len = 0; if (!result) result = Z_InsertZcodeChecksum(keyblock, notice, buffer, cksum_start, cksum_len, cstart, cend, buffer_len, &phdr_adj, 0); if (!result) *phdr_len += phdr_adj; if (notice->z_ascii_authent != NULL) free(notice->z_ascii_authent); krb5_free_data_contents(Z_krb5_ctx, authent); if (authent != NULL) free(authent); return result; }
int _GetSecurityObject(struct afscp_cell *cell) { int code = ENOENT; #ifdef HAVE_KERBEROS krb5_context context; krb5_creds match; krb5_creds *cred; krb5_ccache cc; char **realms, *realm; struct afsconf_cell celldata; char localcell[MAXCELLCHARS + 1]; struct rx_securityClass *sc; struct ktc_encryptionKey k; int i; rxkad_level l; code = _GetCellInfo(cell->name, &celldata); if (code != 0) { goto try_anon; } if (authas_name[0]) { code = _GetLocalSecurityObject(cell, authas_name, authas_inst); if (code == 0) { return 0; } } code = krb5_init_context(&context); /* see aklog.c main() */ if (code != 0) { goto try_anon; } if (cell->realm == NULL) { realm = NULL; code = krb5_get_host_realm(context, celldata.hostName[0], &realms); if (code == 0) { strlcpy(localcell, realms[0], sizeof(localcell)); krb5_free_host_realm(context, realms); realm = localcell; } else goto try_anon; } else { realm = cell->realm; strlcpy(localcell, realm, MAXCELLCHARS + 1); } if (realm) if (realm == NULL) { for (i = 0; (i < MAXCELLCHARS && cell->name[i]); i++) { if (isalpha(cell->name[i])) localcell[i] = toupper(cell->name[i]); else localcell[i] = cell->name[i]; } localcell[i] = '\0'; realm = localcell; } cc = NULL; code = krb5_cc_default(context, &cc); memset(&match, 0, sizeof(match)); Z_enctype(Z_credskey(&match)) = ENCTYPE_DES_CBC_CRC; if (code == 0) code = krb5_cc_get_principal(context, cc, &match.client); if (code == 0) code = krb5_build_principal(context, &match.server, strlen(realm), realm, "afs", cell->name, NULL); if (code != 0) { krb5_free_cred_contents(context, &match); if (cc) krb5_cc_close(context, cc); krb5_free_context(context); goto try_anon; } code = krb5_get_credentials(context, 0, cc, &match, &cred); if (code != 0) { krb5_free_principal(context, match.server); match.server = NULL; code = krb5_build_principal(context, &match.server, strlen(realm), realm, "afs", NULL); if (code == 0) code = krb5_get_credentials(context, 0, cc, &match, &cred); if (code != 0) { krb5_free_cred_contents(context, &match); if (cc) krb5_cc_close(context, cc); krb5_free_context(context); goto try_anon; } } if (insecure) l = rxkad_clear; else l = rxkad_crypt; memcpy(&k.data, Z_keydata(Z_credskey(cred)), 8); sc = (struct rx_securityClass *)rxkad_NewClientSecurityObject (l, &k, RXKAD_TKT_TYPE_KERBEROS_V5, cred->ticket.length, cred->ticket.data); krb5_free_creds(context, cred); krb5_free_cred_contents(context, &match); if (cc) krb5_cc_close(context, cc); krb5_free_context(context); cell->security = sc; cell->scindex = 2; return 0; try_anon: #endif /* HAVE_KERBEROS */ if (try_anonymous) return _GetNullSecurityObject(cell); else return code; }
Code_t Z_MakeAuthenticationSaveKey(register ZNotice_t *notice, char *buffer, int buffer_len, int *len) { #ifndef HAVE_KRB5 /* Key management not implemented for krb4. */ return ZMakeAuthentication(notice, buffer, buffer_len, len); #else Code_t result; krb5_creds *creds = NULL; krb5_keyblock *keyblock; struct _Z_SessionKey *savedkey; /* Look up creds and checksum the notice. */ if ((result = ZGetCreds(&creds))) return result; if ((result = Z_MakeZcodeAuthentication(notice, buffer, buffer_len, len, creds))) { krb5_free_creds(Z_krb5_ctx, creds); return result; } /* Save the key. */ keyblock = Z_credskey(creds); if (Z_keys_head && Z_keys_head->keyblock->enctype == keyblock->enctype && Z_keys_head->keyblock->length == keyblock->length && memcmp(Z_keys_head->keyblock->contents, keyblock->contents, keyblock->length) == 0) { /* * Optimization: if the key hasn't changed, replace the current entry, * rather than make a new one. */ Z_keys_head->send_time = time(NULL); Z_keys_head->first_use = 0; } else { savedkey = (struct _Z_SessionKey *)malloc(sizeof(struct _Z_SessionKey)); if (!savedkey) { krb5_free_creds(Z_krb5_ctx, creds); return ENOMEM; } if ((result = krb5_copy_keyblock(Z_krb5_ctx, keyblock, &savedkey->keyblock))) { free(savedkey); krb5_free_creds(Z_krb5_ctx, creds); return result; } savedkey->send_time = time(NULL); savedkey->first_use = 0; savedkey->prev = NULL; savedkey->next = Z_keys_head; if (Z_keys_head) Z_keys_head->prev = savedkey; Z_keys_head = savedkey; if (!Z_keys_tail) Z_keys_tail = savedkey; } krb5_free_creds(Z_krb5_ctx, creds); return result; #endif }