📄 kssl.c
字号:
int xx = 0, yy = 0; if (*p++ != 0x62) return 0; if (*p > 0x82) return 0; switch(*p) { case 0x82: p++; xx = (*p++ << 8); xx += *p++; break; case 0x81: p++; xx = *p++; break; case 0x80: return 0; default: xx = *p++; break; } if (*p++ != 0x30) return 0; if (*p > 0x82) return 0; switch(*p) { case 0x82: p++; len+=2; yy = (*p++ << 8); yy += *p++; break; case 0x81: p++; len++; yy = *p++; break; case 0x80: return 0; default: yy = *p++; break; } return (xx - len == yy)? 1: 0; }/* Allocate, fill, and return cksumlens array of checksum lengths.** This array holds just the unique elements from the krb5_cksumarray[].** array[n] == 0 signals end of data.**** The krb5_cksumarray[] was an internal variable that has since been** replaced by a more general method for storing the data. It should** not be used. Instead we use real API calls and make a guess for ** what the highest assigned CKSUMTYPE_ constant is. As of 1.2.2** it is 0x000c (CKSUMTYPE_HMAC_SHA1_DES3). So we will use 0x0010.*/size_t *populate_cksumlens(void) { int i, j, n; static size_t *cklens = NULL;#ifdef KRB5_MIT_OLD11 n = krb5_max_cksum;#else n = 0x0010;#endif /* KRB5_MIT_OLD11 */ #ifdef KRB5CHECKAUTH if (!cklens && !(cklens = (size_t *) calloc(sizeof(int),n+1))) return NULL; for (i=0; i < n; i++) { if (!valid_cksumtype(i)) continue; /* array has holes */ for (j=0; j < n; j++) { if (cklens[j] == 0) { cklens[j] = krb5_checksum_size(NULL,i); break; /* krb5 elem was new: add */ } if (cklens[j] == krb5_checksum_size(NULL,i)) { break; /* ignore duplicate elements */ } } }#endif /* KRB5CHECKAUTH */ return cklens; }/* Return pointer to start of real authenticator within authenticator, or** return NULL on error.** Decrypted authenticator looks like this:** [0 or 8 byte confounder] [4-24 byte checksum] [real authent'r]** This hackery wouldn't be necessary if MIT KRB5 1.0.6 had the** krb5_auth_con_getcksumtype() function advertised in its krb5.h.*/unsigned char *kssl_skip_confound(krb5_enctype etype, unsigned char *a) { int i, conlen; size_t cklen; static size_t *cksumlens = NULL; unsigned char *test_auth; conlen = (etype)? 8: 0; if (!cksumlens && !(cksumlens = populate_cksumlens())) return NULL; for (i=0; (cklen = cksumlens[i]) != 0; i++) { test_auth = a + conlen + cklen; if (kssl_test_confound(test_auth)) return test_auth; } return NULL; }/* Set kssl_err error info when reason text is a simple string** kssl_err = struct { int reason; char text[KSSL_ERR_MAX+1]; }*/voidkssl_err_set(KSSL_ERR *kssl_err, int reason, char *text) { if (kssl_err == NULL) return; kssl_err->reason = reason; BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, text); return; }/* Display contents of krb5_data struct, for debugging*/voidprint_krb5_data(char *label, krb5_data *kdata) { int i; printf("%s[%d] ", label, kdata->length); for (i=0; i < (int)kdata->length; i++) { if (0 && isprint((int) kdata->data[i])) printf( "%c ", kdata->data[i]); else printf( "%02x ", (unsigned char) kdata->data[i]); } printf("\n"); }/* Display contents of krb5_authdata struct, for debugging*/voidprint_krb5_authdata(char *label, krb5_authdata **adata) { if (adata == NULL) { printf("%s, authdata==0\n", label); return; } printf("%s [%p]\n", label, (void *)adata);#if 0 { int i; printf("%s[at%d:%d] ", label, adata->ad_type, adata->length); for (i=0; i < adata->length; i++) { printf((isprint(adata->contents[i]))? "%c ": "%02x", adata->contents[i]); } printf("\n"); }#endif }/* Display contents of krb5_keyblock struct, for debugging*/voidprint_krb5_keyblock(char *label, krb5_keyblock *keyblk) { int i; if (keyblk == NULL) { printf("%s, keyblk==0\n", label); return; }#ifdef KRB5_HEIMDAL printf("%s\n\t[et%d:%d]: ", label, keyblk->keytype, keyblk->keyvalue->length); for (i=0; i < (int)keyblk->keyvalue->length; i++) { printf("%02x",(unsigned char *)(keyblk->keyvalue->contents)[i]); } printf("\n");#else printf("%s\n\t[et%d:%d]: ", label, keyblk->enctype, keyblk->length); for (i=0; i < (int)keyblk->length; i++) { printf("%02x",keyblk->contents[i]); } printf("\n");#endif }/* Display contents of krb5_principal_data struct, for debugging** (krb5_principal is typedef'd == krb5_principal_data *)*/voidprint_krb5_princ(char *label, krb5_principal_data *princ) { int i, ui, uj; printf("%s principal Realm: ", label); if (princ == NULL) return; for (ui=0; ui < (int)princ->realm.length; ui++) putchar(princ->realm.data[ui]); printf(" (nametype %d) has %d strings:\n", princ->type,princ->length); for (i=0; i < (int)princ->length; i++) { printf("\t%d [%d]: ", i, princ->data[i].length); for (uj=0; uj < (int)princ->data[i].length; uj++) { putchar(princ->data[i].data[uj]); } printf("\n"); } return; }/* Given krb5 service (typically "kssl") and hostname in kssl_ctx,** Return encrypted Kerberos ticket for service @ hostname.** If authenp is non-NULL, also return encrypted authenticator,** whose data should be freed by caller.** (Originally was: Create Kerberos AP_REQ message for SSL Client.)**** 19990628 VRS Started; Returns Kerberos AP_REQ message.** 20010409 VRS Modified for RFC2712; Returns enc tkt.** 20010606 VRS May also return optional authenticator.*/krb5_error_codekssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, /* OUT */ krb5_data **enc_ticketp, /* UPDATE */ krb5_data *authenp, /* OUT */ KSSL_ERR *kssl_err) { krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; krb5_context krb5context = NULL; krb5_auth_context krb5auth_context = NULL; krb5_ccache krb5ccdef = NULL; krb5_creds krb5creds, *krb5credsp = NULL; krb5_data krb5_app_req; kssl_err_set(kssl_err, 0, ""); memset((char *)&krb5creds, 0, sizeof(krb5creds)); if (!kssl_ctx) { kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, "No kssl_ctx defined.\n"); goto err; } else if (!kssl_ctx->service_host) { kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, "kssl_ctx service_host undefined.\n"); goto err; } if ((krb5rc = krb5_init_context(&krb5context)) != 0) { BIO_snprintf(kssl_err->text,KSSL_ERR_MAX, "krb5_init_context() fails: %d\n", krb5rc); kssl_err->reason = SSL_R_KRB5_C_INIT; goto err; } if ((krb5rc = krb5_sname_to_principal(krb5context, kssl_ctx->service_host, (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC, KRB5_NT_SRV_HST, &krb5creds.server)) != 0) { BIO_snprintf(kssl_err->text,KSSL_ERR_MAX, "krb5_sname_to_principal() fails for %s/%s\n", kssl_ctx->service_host, (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC); kssl_err->reason = SSL_R_KRB5_C_INIT; goto err; } if ((krb5rc = krb5_cc_default(krb5context, &krb5ccdef)) != 0) { kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, "krb5_cc_default fails.\n"); goto err; } if ((krb5rc = krb5_cc_get_principal(krb5context, krb5ccdef, &krb5creds.client)) != 0) { kssl_err_set(kssl_err, SSL_R_KRB5_C_CC_PRINC, "krb5_cc_get_principal() fails.\n"); goto err; } if ((krb5rc = krb5_get_credentials(krb5context, 0, krb5ccdef, &krb5creds, &krb5credsp)) != 0) { kssl_err_set(kssl_err, SSL_R_KRB5_C_GET_CRED, "krb5_get_credentials() fails.\n"); goto err; } *enc_ticketp = &krb5credsp->ticket;#ifdef KRB5_HEIMDAL kssl_ctx->enctype = krb5credsp->session.keytype;#else kssl_ctx->enctype = krb5credsp->keyblock.enctype;#endif krb5rc = KRB5KRB_ERR_GENERIC; /* caller should free data of krb5_app_req */ /* 20010406 VRS deleted for real KerberosWrapper ** 20010605 VRS reinstated to offer Authenticator to KerberosWrapper */ krb5_app_req.length = 0; if (authenp) { krb5_data krb5in_data; const unsigned char *p; long arlen; KRB5_APREQBODY *ap_req; authenp->length = 0; krb5in_data.data = NULL; krb5in_data.length = 0; if ((krb5rc = krb5_mk_req_extended(krb5context, &krb5auth_context, 0, &krb5in_data, krb5credsp, &krb5_app_req)) != 0) { kssl_err_set(kssl_err, SSL_R_KRB5_C_MK_REQ, "krb5_mk_req_extended() fails.\n"); goto err; } arlen = krb5_app_req.length; p = (unsigned char *)krb5_app_req.data; ap_req = (KRB5_APREQBODY *) d2i_KRB5_APREQ(NULL, &p, arlen); if (ap_req) { authenp->length = i2d_KRB5_ENCDATA( ap_req->authenticator, NULL); if (authenp->length && (authenp->data = malloc(authenp->length))) { unsigned char *adp = (unsigned char *)authenp->data; authenp->length = i2d_KRB5_ENCDATA( ap_req->authenticator, &adp); } } if (ap_req) KRB5_APREQ_free((KRB5_APREQ *) ap_req); if (krb5_app_req.length) kssl_krb5_free_data_contents(krb5context,&krb5_app_req); }#ifdef KRB5_HEIMDAL if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session)) { kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, "kssl_ctx_setkey() fails.\n"); }#else if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->keyblock)) { kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, "kssl_ctx_setkey() fails.\n"); }#endif else krb5rc = 0; err:#ifdef KSSL_DEBUG kssl_ctx_show(kssl_ctx);#endif /* KSSL_DEBUG */ if (krb5creds.client) krb5_free_principal(krb5context, krb5creds.client); if (krb5creds.server) krb5_free_principal(krb5context, krb5creds.server); if (krb5auth_context) krb5_auth_con_free(krb5context, krb5auth_context); if (krb5context) krb5_free_context(krb5context); return (krb5rc); }/* Given d2i_-decoded asn1ticket, allocate and return a new krb5_ticket.** Return Kerberos error code and kssl_err struct on error.** Allocates krb5_ticket and krb5_principal; caller should free these.**** 20010410 VRS Implemented krb5_decode_ticket() as** old_krb5_decode_ticket(). Missing from MIT1.0.6.** 20010615 VRS Re-cast as openssl/asn1 d2i_*() functions.** Re-used some of the old krb5_decode_ticket()** code here. This tkt should alloc/free just** like the real thing.*/krb5_error_codekssl_TKT2tkt( /* IN */ krb5_context krb5context, /* IN */ KRB5_TKTBODY *asn1ticket, /* OUT */ krb5_ticket **krb5ticket, /* OUT */ KSSL_ERR *kssl_err ) { krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; krb5_ticket *new5ticket = NULL; ASN1_GENERALSTRING *gstr_svc, *gstr_host; *krb5ticket = NULL; if (asn1ticket == NULL || asn1ticket->realm == NULL || asn1ticket->sname == NULL || sk_ASN1_GENERALSTRING_num(asn1ticket->sname->namestring) < 2) { BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, "Null field in asn1ticket.\n"); kssl_err->reason = SSL_R_KRB5_S_RD_REQ; return KRB5KRB_ERR_GENERIC; } if ((new5ticket = (krb5_ticket *) calloc(1, sizeof(krb5_ticket)))==NULL) { BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, "Unable to allocate new krb5_ticket.\n"); kssl_err->reason = SSL_R_KRB5_S_RD_REQ; return ENOMEM; /* or KRB5KRB_ERR_GENERIC; */ } gstr_svc = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 0); gstr_host = sk_ASN1_GENERALSTRING_value(asn1ticket->sname->namestring, 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -