/** * shishi_tgs_rep_der: * @tgs: structure that holds information about TGS exchange * @out: output array with newly allocated DER encoding of TGS-REP. * @outlen: length of output array with DER encoding of TGS-REP. * * DER encode TGS-REP. @out is allocated by this function, and it is * the responsibility of caller to deallocate it. * * Return value: Returns SHISHI_OK iff successful. **/ int shishi_tgs_rep_der (Shishi_tgs * tgs, char **out, size_t * outlen) { int rc; rc = shishi_asn1_to_der (tgs->handle, tgs->tgsrep, out, outlen); if (rc != SHISHI_OK) return rc; return SHISHI_OK; }
/** * shishi_kdcreq_add_padata_tgs: * @handle: shishi handle as allocated by shishi_init(). * @kdcreq: KDC-REQ to add PA-DATA to. * @apreq: AP-REQ to add as PA-DATA. * * Add TGS pre-authentication data to KDC-REQ. The data is an AP-REQ * that authenticates the request. This functions simply DER encodes * the AP-REQ and calls shishi_kdcreq_add_padata() with a * SHISHI_PA_TGS_REQ padatatype. * * Return value: Returns SHISHI_OK iff successful. **/ int shishi_kdcreq_add_padata_tgs (Shishi * handle, Shishi_asn1 kdcreq, Shishi_asn1 apreq) { int res; char *data; size_t datalen; res = shishi_asn1_to_der (handle, apreq, &data, &datalen); if (res != SHISHI_OK) { shishi_error_printf (handle, "Could not DER encode AP-REQ: %s\n", shishi_strerror (res)); return res; } res = shishi_kdcreq_add_padata (handle, kdcreq, SHISHI_PA_TGS_REQ, data, datalen); free (data); if (res != SHISHI_OK) return res; return res; }
/** * shishi_apreq_add_authenticator: * @handle: shishi handle as allocated by shishi_init(). * @apreq: AP-REQ to add authenticator field to. * @key: key to to use for encryption. * @keyusage: cryptographic key usage value to use in encryption. * @authenticator: authenticator as allocated by shishi_authenticator(). * * Encrypts DER encoded authenticator using key and store it in the * AP-REQ. * * Return value: Returns SHISHI_OK iff successful. **/ int shishi_apreq_add_authenticator (Shishi * handle, Shishi_asn1 apreq, Shishi_key * key, int keyusage, Shishi_asn1 authenticator) { int res; char *buf; size_t buflen; char *der; size_t derlen; res = shishi_asn1_to_der (handle, authenticator, &der, &derlen); if (res != SHISHI_OK) { shishi_error_printf (handle, "Could not DER encode authenticator: %s\n", shishi_strerror (res)); return res; } res = shishi_encrypt (handle, key, keyusage, der, derlen, &buf, &buflen); free (der); if (res != SHISHI_OK) { shishi_error_printf (handle, "Cannot encrypt authenticator.\n"); return res; } res = shishi_apreq_set_authenticator (handle, apreq, shishi_key_type (key), shishi_key_version (key), buf, buflen); return res; }
/** * shishi_kdcreq_add_padata_preauth: * @handle: shishi handle as allocated by shishi_init(). * @kdcreq: KDC-REQ to add pre-authentication data to. * @key: Key used to encrypt pre-auth data. * * Add pre-authentication data to KDC-REQ. * * Return value: Returns SHISHI_OK iff successful. **/ int shishi_kdcreq_add_padata_preauth (Shishi * handle, Shishi_asn1 kdcreq, Shishi_key * key) { char *der, *data; size_t derlen, datalen; Shishi_asn1 pa; struct timeval tv; int rc; Shishi_asn1 ed; pa = shishi_asn1_pa_enc_ts_enc (handle); if (!pa) return SHISHI_ASN1_ERROR; rc = gettimeofday (&tv, NULL); if (rc != 0) return SHISHI_GETTIMEOFDAY_ERROR; rc = shishi_asn1_write (handle, pa, "patimestamp", shishi_generalize_time (handle, tv.tv_sec), SHISHI_GENERALIZEDTIME_LENGTH); if (rc != SHISHI_OK) return rc; rc = shishi_asn1_write_integer (handle, pa, "pausec", tv.tv_usec); if (rc != SHISHI_OK) return rc; rc = shishi_asn1_to_der (handle, pa, &der, &derlen); if (rc != SHISHI_OK) return rc; rc = shishi_encrypt (handle, key, SHISHI_KEYUSAGE_ASREQ_PA_ENC_TIMESTAMP, der, derlen, &data, &datalen); free (der); if (rc != SHISHI_OK) return rc; ed = shishi_asn1_encrypteddata (handle); if (!ed) return SHISHI_ASN1_ERROR; rc = shishi_asn1_write_integer (handle, ed, "etype", shishi_key_type (key)); if (rc != SHISHI_OK) return rc; rc = shishi_asn1_write (handle, ed, "cipher", data, datalen); if (rc != SHISHI_OK) return rc; rc = shishi_asn1_write (handle, ed, "kvno", NULL, 0); if (rc != SHISHI_OK) return rc; rc = shishi_asn1_to_der (handle, ed, &der, &derlen); free (data); if (rc != SHISHI_OK) return rc; rc = shishi_kdcreq_add_padata (handle, kdcreq, SHISHI_PA_ENC_TIMESTAMP, der, derlen); free (der); if (rc != SHISHI_OK) return rc; return rc; }
/* Allows a remotely initiated security context between the application and a remote peer to be established, using krb5. Assumes context_handle is valid. */ OM_uint32 gss_krb5_accept_sec_context (OM_uint32 * minor_status, gss_ctx_id_t * context_handle, const gss_cred_id_t acceptor_cred_handle, const gss_buffer_t input_token_buffer, const gss_channel_bindings_t input_chan_bindings, gss_name_t * src_name, gss_OID * mech_type, gss_buffer_t output_token, OM_uint32 * ret_flags, OM_uint32 * time_rec, gss_cred_id_t * delegated_cred_handle) { gss_buffer_desc data; char *in; size_t inlen; gss_ctx_id_t cx; _gss_krb5_ctx_t cxk5; _gss_krb5_cred_t crk5; int rc; if (minor_status) *minor_status = 0; if (ret_flags) *ret_flags = 0; if (!acceptor_cred_handle) /* XXX support GSS_C_NO_CREDENTIAL: acquire_cred() default server */ return GSS_S_NO_CRED; if (*context_handle) return GSS_S_FAILURE; crk5 = acceptor_cred_handle->krb5; cx = calloc (sizeof (*cx), 1); if (!cx) { if (minor_status) *minor_status = ENOMEM; return GSS_S_FAILURE; } cxk5 = calloc (sizeof (*cxk5), 1); if (!cxk5) { free (cx); if (minor_status) *minor_status = ENOMEM; return GSS_S_FAILURE; } cx->mech = GSS_KRB5; cx->krb5 = cxk5; /* XXX cx->peer?? */ *context_handle = cx; cxk5->sh = crk5->sh; cxk5->key = crk5->key; cxk5->acceptor = 1; rc = shishi_ap (cxk5->sh, &cxk5->ap); if (rc != SHISHI_OK) return GSS_S_FAILURE; rc = gss_decapsulate_token (input_token_buffer, GSS_KRB5, &in, &inlen); if (!rc) return GSS_S_BAD_MIC; if (inlen < TOK_LEN) return GSS_S_BAD_MIC; if (memcmp (in, TOK_AP_REQ, TOK_LEN) != 0) return GSS_S_BAD_MIC; rc = shishi_ap_req_der_set (cxk5->ap, in + TOK_LEN, inlen - TOK_LEN); if (rc != SHISHI_OK) return GSS_S_FAILURE; rc = shishi_ap_req_process (cxk5->ap, crk5->key); if (rc != SHISHI_OK) { if (minor_status) *minor_status = GSS_KRB5_S_G_VALIDATE_FAILED; return GSS_S_FAILURE; } rc = shishi_authenticator_seqnumber_get (cxk5->sh, shishi_ap_authenticator (cxk5->ap), &cxk5->initseqnr); if (rc != SHISHI_OK) return GSS_S_FAILURE; rc = _gss_krb5_checksum_parse (minor_status, context_handle, input_chan_bindings); if (rc != GSS_S_COMPLETE) return GSS_S_FAILURE; cxk5->tkt = shishi_ap_tkt (cxk5->ap); cxk5->key = shishi_ap_key (cxk5->ap); if (shishi_apreq_mutual_required_p (crk5->sh, shishi_ap_req (cxk5->ap))) { Shishi_asn1 aprep; rc = shishi_ap_rep_asn1 (cxk5->ap, &aprep); if (rc != SHISHI_OK) { printf ("Error creating AP-REP: %s\n", shishi_strerror (rc)); return GSS_S_FAILURE; } rc = shishi_encapreppart_seqnumber_get (cxk5->sh, shishi_ap_encapreppart (cxk5-> ap), &cxk5->acceptseqnr); if (rc != SHISHI_OK) { /* A strict 1964 implementation would return GSS_S_DEFECTIVE_TOKEN here. gssapi-cfx permit absent sequence number, though. */ cxk5->acceptseqnr = 0; } { char *der; size_t len; rc = shishi_asn1_to_der (crk5->sh, aprep, &der, &len); if (rc != SHISHI_OK) { printf ("Error der encoding aprep: %s\n", shishi_strerror (rc)); return GSS_S_FAILURE; } data.value = der; data.length = len; } rc = gss_encapsulate_token_prefix (&data, TOK_AP_REP, TOK_LEN, GSS_KRB5, output_token); if (!rc) return GSS_S_FAILURE; if (ret_flags) *ret_flags = GSS_C_MUTUAL_FLAG; } else { output_token->value = NULL; output_token->length = 0; } if (src_name) { gss_name_t p; p = malloc (sizeof (*p)); if (!p) { if (minor_status) *minor_status = ENOMEM; return GSS_S_FAILURE; } rc = shishi_encticketpart_client (cxk5->sh, shishi_tkt_encticketpart (cxk5->tkt), &p->value, &p->length); if (rc != SHISHI_OK) return GSS_S_FAILURE; p->type = GSS_KRB5_NT_PRINCIPAL_NAME; *src_name = p; } /* PROT_READY is not mentioned in 1964/gssapi-cfx but we support it anyway. */ if (ret_flags) *ret_flags |= GSS_C_PROT_READY_FLAG; if (minor_status) *minor_status = 0; return GSS_S_COMPLETE; }
void test (Shishi * handle) { Shishi_asn1 a; char *p, *buf, *buf2; int res; size_t n, m; int32_t t; uint32_t s; /* shishi_authenticator */ a = shishi_authenticator (handle); if (debug) printf ("shishi_authenticator () => `%p'.\n", a); if (a) success ("shishi_authenticator() OK\n"); else fail ("shishi_authenticator() failed\n"); if (debug) shishi_authenticator_print (handle, stdout, a); res = shishi_authenticator_remove_subkey (handle, a); if (res == SHISHI_OK) success ("shishi_authenticator_remove_subkey() OK\n"); else fail ("shishi_authenticator_remove_subkey() failed\n"); /* shishi_authenticator_seqnumber_get */ res = shishi_authenticator_seqnumber_get (handle, a, &s); if (res == SHISHI_OK) success ("shishi_authenticator_seqnumber_get() OK\n"); else fail ("shishi_authenticator_seqnumber_get() failed\n"); /* shishi_authenticator_seqnumber_set */ res = shishi_authenticator_seqnumber_set (handle, a, 42); if (res == SHISHI_OK) success ("shishi_authenticator_seqnumber_set() OK\n"); else fail ("shishi_authenticator_seqnumber_set() failed\n"); /* shishi_authenticator_seqnumber_get */ res = shishi_authenticator_seqnumber_get (handle, a, &s); if (res == SHISHI_OK && s == 42) success ("shishi_authenticator_seqnumber_get() OK\n"); else fail ("shishi_authenticator_seqnumber_get() failed\n"); /* shishi_authenticator_seqnumber_remove */ res = shishi_authenticator_seqnumber_remove (handle, a); if (res == SHISHI_OK) success ("shishi_authenticator_seqnumber_remove() OK\n"); else fail ("shishi_authenticator_seqnumber_remove() failed\n"); /* shishi_authenticator_set_crealm */ res = shishi_authenticator_set_crealm (handle, a, "foo"); if (res == SHISHI_OK) success ("shishi_authenticator_set_crealm() OK\n"); else fail ("shishi_authenticator_set_crealm() failed\n"); /* shishi_authenticator_client_set */ res = shishi_authenticator_client_set (handle, a, "foo/bar/baz"); if (res == SHISHI_OK) success ("shishi_authenticator_client_set() OK\n"); else fail ("shishi_authenticator_client_set() failed\n"); /* shishi_authenticator_client */ res = shishi_authenticator_client (handle, a, &buf, &n); if (debug) escapeprint (buf, n); if (res == SHISHI_OK && n == strlen ("foo/bar/baz") && memcmp (buf, "foo/bar/baz", n) == 0) success ("shishi_authenticator_client() OK\n"); else fail ("shishi_authenticator_client() failed\n"); if (res == SHISHI_OK) free (buf); /* shishi_authenticator_client_set */ res = shishi_authenticator_client_set (handle, a, "foo"); if (res == SHISHI_OK) success ("shishi_authenticator_client_set() OK\n"); else fail ("shishi_authenticator_client_set() failed\n"); /* shishi_authenticator_client */ res = shishi_authenticator_client (handle, a, &buf, &n); if (debug) escapeprint (buf, n); if (res == SHISHI_OK && n == strlen ("foo") && memcmp (buf, "foo", n) == 0) success ("shishi_authenticator_client() OK\n"); else fail ("shishi_authenticator_client() failed\n"); if (res == SHISHI_OK) free (buf); /* shishi_authenticator_set_crealm */ res = shishi_authenticator_set_crealm (handle, a, "bar"); if (res == SHISHI_OK) success ("shishi_authenticator_set_crealm() OK\n"); else fail ("shishi_authenticator_set_crealm() failed\n"); /* shishi_authenticator_clientrealm */ res = shishi_authenticator_clientrealm (handle, a, &buf, &n); if (debug) escapeprint (buf, n); if (res == SHISHI_OK && n == strlen ("foo@bar") && memcmp (buf, "foo@bar", n) == 0) success ("shishi_authenticator_clientrealm() OK\n"); else fail ("shishi_authenticator_clientrealm() failed\n"); if (res == SHISHI_OK) free (buf); /* shishi_authenticator_add_authorizationdata */ res = shishi_authenticator_add_authorizationdata (handle, a, 42, "baz", 3); if (res == SHISHI_OK) success ("shishi_authenticator_add_authorizationdata() OK\n"); else fail ("shishi_authenticator_add_authorizationdata() failed\n"); /* shishi_authenticator_authorizationdata */ res = shishi_authenticator_authorizationdata (handle, a, &t, &buf, &m, 1); if (debug) escapeprint (buf, m); if (res == SHISHI_OK && t == 42 && m == 3 && memcmp (buf, "baz", 3) == 0) success ("shishi_authenticator_authorizationdata() OK\n"); else fail ("shishi_authenticator_authorizationdata() failed\n"); if (res == SHISHI_OK) free (buf); /* shishi_authenticator_authorizationdata */ res = shishi_authenticator_authorizationdata (handle, a, &t, &buf, &m, 2); if (res == SHISHI_OK) free (buf); if (res == SHISHI_OUT_OF_RANGE) success ("shishi_authenticator_authorizationdata() OK\n"); else fail ("shishi_authenticator_authorizationdata() failed\n"); /* shishi_authenticator_remove_cksum */ res = shishi_authenticator_remove_cksum (handle, a); if (res == SHISHI_OK) success ("shishi_authenticator_remove_cksum() OK\n"); else fail ("shishi_authenticator_remove_cksum() failed\n"); /* shishi_asn1_to_der */ res = shishi_asn1_to_der (handle, a, &buf, &n); if (res == SHISHI_OK) success ("shishi_asn1_to_der() OK\n"); else n = 0, fail ("shishi_asn1_to_der() failed\n"); /* shishi_authenticator_to_file */ res = shishi_authenticator_to_file (handle, a, SHISHI_FILETYPE_TEXT, "authenticator.tmp"); if (res == SHISHI_OK) success ("shishi_authenticator_to_file() OK\n"); else fail ("shishi_authenticator_to_file() failed\n"); /* shishi_asn1_done */ shishi_asn1_done (handle, a); success ("shishi_asn1_done() OK\n"); a = NULL; /* shishi_authenticator_from_file */ res = shishi_authenticator_from_file (handle, &a, SHISHI_FILETYPE_TEXT, "authenticator.tmp"); if (res == SHISHI_OK) success ("shishi_authenticator_from_file() OK\n"); else fail ("shishi_authenticator_from_file() failed\n"); if (debug) { /* shishi_authenticator_print */ res = shishi_authenticator_print (handle, stdout, a); if (res == SHISHI_OK) success ("shishi_authenticator_print() OK\n"); else fail ("shishi_authenticator_print() failed\n"); } /* shishi_asn1_to_der */ res = shishi_asn1_to_der (handle, a, &buf2, &m); if (res == SHISHI_OK) success ("shishi_asn1_to_der() OK\n"); else n = 0, fail ("shishi_asn1_to_der() failed\n"); /* Compare DER encodings of authenticators */ if (n > 0 && m > 0 && n == m && memcmp (buf, buf2, n) == 0) success ("DER comparison OK\n"); else fail ("DER comparison failed\n"); free (buf); free (buf2); /* shishi_authenticator_cusec_set */ res = shishi_authenticator_cusec_set (handle, a, 4711); if (res == SHISHI_OK) success ("shishi_authenticator_cusec_set() OK\n"); else fail ("shishi_authenticator_cusec_set() failed\n"); /* shishi_authenticator_cusec_get */ res = shishi_authenticator_cusec_get (handle, a, &s); if (debug) printf ("shishi_authenticator_cusec_get () => `%d'.\n", t); if (res == SHISHI_OK && s == 4711) success ("shishi_authenticator_cusec_get() OK\n"); else fail ("shishi_authenticator_cusec_get() failed\n"); /* shishi_authenticator_ctime_set */ res = shishi_authenticator_ctime_set (handle, a, "19700101011831Z"); if (res == SHISHI_OK) success ("shishi_authenticator_ctime_set() OK\n"); else fail ("shishi_authenticator_ctime_set() failed\n"); /* shishi_authenticator_ctime */ res = shishi_authenticator_ctime (handle, a, &p); if (debug) escapeprint (p, strlen (p)); if (res == SHISHI_OK && memcmp (p, "19700101011831Z", 15) == 0) success ("shishi_authenticator_ctime() OK\n"); else fail ("shishi_authenticator_ctime() failed\n"); if (res == SHISHI_OK) free (p); /* shishi_asn1_to_der */ res = shishi_asn1_to_der (handle, a, &buf, &n); if (res == SHISHI_OK) success ("shishi_asn1_to_der() OK\n"); else n = 0, fail ("shishi_asn1_to_der() failed\n"); if (debug) { shishi_authenticator_print (handle, stdout, a); hexprint (buf, n); puts (""); hexprint (authenticator, sizeof (authenticator)); puts (""); } if (n == sizeof (authenticator) && n == AUTHENTICATOR_LEN && memcmp (authenticator, buf, n) == 0) success ("DER comparison OK\n"); else fail ("DER comparison failed\n"); free (buf); /* shishi_authenticator_clear_authorizationdata */ res = shishi_authenticator_clear_authorizationdata (handle, a); if (res == SHISHI_OK) success ("shishi_authenticator_clear_authorizationdata() OK\n"); else fail ("shishi_authenticator_clear_authorizationdata() failed\n"); /* shishi_asn1_to_der */ res = shishi_asn1_to_der (handle, a, &buf, &n); if (res == SHISHI_OK) success ("shishi_asn1_to_der() OK\n"); else n = 0, fail ("shishi_asn1_to_der() failed\n"); if (debug) { shishi_authenticator_print (handle, stdout, a); hexprint (buf, n); puts (""); hexprint (authenticator2, sizeof (authenticator2)); puts (""); } if (n == sizeof (authenticator2) && n == AUTHENTICATOR2_LEN && memcmp (authenticator2, buf, n) == 0) success ("DER comparison OK\n"); else fail ("DER comparison failed\n"); free (buf); /* unlink */ res = unlink ("authenticator.tmp"); if (res == 0) success ("unlink() OK\n"); else fail ("unlink() failed\n"); /* shishi_asn1_done */ shishi_asn1_done (handle, a); success ("shishi_asn1_done() OK\n"); }