static krb5_error_code make_proxy_request(struct conn_state *state, const krb5_data *realm, const krb5_data *message, char **req_out, size_t *len_out) { krb5_kkdcp_message pm; krb5_data *encoded_pm = NULL; struct k5buf buf; const char *uri_path; krb5_error_code ret; *req_out = NULL; *len_out = 0; /* * Stuff the message length in at the front of the kerb_message field * before encoding. The proxied messages are actually the payload we'd * be sending and receiving if we were using plain TCP. */ memset(&pm, 0, sizeof(pm)); ret = alloc_data(&pm.kerb_message, message->length + 4); if (ret != 0) goto cleanup; store_32_be(message->length, pm.kerb_message.data); memcpy(pm.kerb_message.data + 4, message->data, message->length); pm.target_domain = *realm; ret = encode_krb5_kkdcp_message(&pm, &encoded_pm); if (ret != 0) goto cleanup; /* Build the request to transmit: the headers + the proxy message. */ k5_buf_init_dynamic(&buf); uri_path = (state->http.uri_path != NULL) ? state->http.uri_path : ""; k5_buf_add_fmt(&buf, "POST /%s HTTP/1.0\r\n", uri_path); k5_buf_add(&buf, "Cache-Control: no-cache\r\n"); k5_buf_add(&buf, "Pragma: no-cache\r\n"); k5_buf_add(&buf, "User-Agent: kerberos/1.0\r\n"); k5_buf_add(&buf, "Content-type: application/kerberos\r\n"); k5_buf_add_fmt(&buf, "Content-Length: %d\r\n\r\n", encoded_pm->length); k5_buf_add_len(&buf, encoded_pm->data, encoded_pm->length); if (k5_buf_status(&buf) != 0) { ret = ENOMEM; goto cleanup; } *req_out = buf.data; *len_out = buf.len; cleanup: krb5_free_data_contents(NULL, &pm.kerb_message); krb5_free_data(NULL, encoded_pm); return ret; }
/* * Write a field of bytes from krb5_data as a hexadecimal string. Write empty * strings as "-1" unless requested. */ static int write_data(struct rec_args *args, krb5_data *data) { int ret; char *p; size_t i; struct k5buf buf; struct rechandle *h = args->rh; struct tdopts *opts = args->opts; if (data->length == 0 && !opts->emptyhex_empty) { if (writefield(h, "-1") < 0) return -1; return 0; } k5_buf_init_dynamic(&buf); p = data->data; for (i = 0; i < data->length; i++) k5_buf_add_fmt(&buf, "%02x", (unsigned char)p[i]); if (buf.data == NULL) { errno = ENOMEM; return -1; } ret = writefield(h, "%s", (char *)buf.data); k5_buf_free(&buf); return ret; }
/* Return a copy of in, quoting all characters which are special in an LDAP * filter (RFC 4515) or DN string (RFC 4514). Return NULL on failure. */ char * ldap_filter_correct (char *in) { size_t count; const char special[] = "*()\\ #\"+,;<>"; struct k5buf buf; k5_buf_init_dynamic(&buf); while (TRUE) { count = strcspn(in, special); k5_buf_add_len(&buf, in, count); in += count; if (*in == '\0') break; k5_buf_add_fmt(&buf, "\\%2x", (unsigned char)*in++); } return buf.data; }
static krb5_error_code krb5_rc_io_store(krb5_context context, struct dfl_data *t, krb5_donot_replay *rep) { size_t clientlen, serverlen; unsigned int len; krb5_error_code ret; struct k5buf buf, extbuf; char *extstr; clientlen = strlen(rep->client); serverlen = strlen(rep->server); if (rep->msghash) { /* * Write a hash extension record, to be followed by a record * in regular format (without the message hash) for the * benefit of old implementations. */ /* Format the extension value so we know its length. */ k5_buf_init_dynamic(&extbuf); k5_buf_add_fmt(&extbuf, "HASH:%s %lu:%s %lu:%s", rep->msghash, (unsigned long)clientlen, rep->client, (unsigned long)serverlen, rep->server); if (k5_buf_status(&extbuf) != 0) return KRB5_RC_MALLOC; extstr = extbuf.data; /* * Put the extension value into the server field of a * regular-format record, with an empty client field. */ k5_buf_init_dynamic(&buf); len = 1; k5_buf_add_len(&buf, (char *)&len, sizeof(len)); k5_buf_add_len(&buf, "", 1); len = strlen(extstr) + 1; k5_buf_add_len(&buf, (char *)&len, sizeof(len)); k5_buf_add_len(&buf, extstr, len); k5_buf_add_len(&buf, (char *)&rep->cusec, sizeof(rep->cusec)); k5_buf_add_len(&buf, (char *)&rep->ctime, sizeof(rep->ctime)); free(extstr); } else /* No extension record needed. */ k5_buf_init_dynamic(&buf); len = clientlen + 1; k5_buf_add_len(&buf, (char *)&len, sizeof(len)); k5_buf_add_len(&buf, rep->client, len); len = serverlen + 1; k5_buf_add_len(&buf, (char *)&len, sizeof(len)); k5_buf_add_len(&buf, rep->server, len); k5_buf_add_len(&buf, (char *)&rep->cusec, sizeof(rep->cusec)); k5_buf_add_len(&buf, (char *)&rep->ctime, sizeof(rep->ctime)); if (k5_buf_status(&buf) != 0) return KRB5_RC_MALLOC; ret = krb5_rc_io_write(context, &t->d, buf.data, buf.len); k5_buf_free(&buf); return ret; }
static krb5_error_code decode_ad_policy_info(const krb5_data *data, char **msg_out) { struct ad_policy_info policy; uint64_t password_days; const char *p; struct k5buf buf; *msg_out = NULL; if (data->length != AD_POLICY_INFO_LENGTH) return 0; p = data->data; policy.zero_bytes = load_16_be(p); p += 2; /* first two bytes are zeros */ if (policy.zero_bytes != 0) return 0; /* Read in the rest of structure */ policy.min_length_password = load_32_be(p); p += 4; policy.password_history = load_32_be(p); p += 4; policy.password_properties = load_32_be(p); p += 4; policy.expire = load_64_be(p); p += 8; policy.min_passwordage = load_64_be(p); p += 8; /* Check that we processed exactly the expected number of bytes. */ assert(p == data->data + AD_POLICY_INFO_LENGTH); k5_buf_init_dynamic(&buf); /* * Update src/tests/misc/test_chpw_message.c if changing these strings! */ if (policy.password_properties & AD_POLICY_COMPLEX) { k5_buf_add(&buf, _("The password must include numbers or symbols. " "Don't include any part of your name in the " "password.")); } if (policy.min_length_password > 0) { add_spaces(&buf); k5_buf_add_fmt(&buf, ngettext("The password must contain at least %d " "character.", "The password must contain at least %d " "characters.", policy.min_length_password), policy.min_length_password); } if (policy.password_history) { add_spaces(&buf); k5_buf_add_fmt(&buf, ngettext("The password must be different from " "the previous password.", "The password must be different from " "the previous %d passwords.", policy.password_history), policy.password_history); } if (policy.min_passwordage) { password_days = policy.min_passwordage / AD_POLICY_TIME_TO_DAYS; if (password_days == 0) password_days = 1; add_spaces(&buf); k5_buf_add_fmt(&buf, ngettext("The password can only be changed once " "a day.", "The password can only be changed every " "%d days.", (int)password_days), (int)password_days); } if (k5_buf_status(&buf) != 0) return ENOMEM; if (buf.len > 0) *msg_out = buf.data; else k5_buf_free(&buf); return 0; }
static void test_hmac() { krb5_keyblock key; krb5_data in, out; char outbuf[20]; char stroutbuf[80]; krb5_error_code err; unsigned int i, j; int lose = 0; struct k5buf buf; /* RFC 2202 test vector. */ static const struct hmac_test md5tests[] = { { 16, { 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, 0xb, }, 8, "Hi There", "0x9294727a3638bb1c13f48ef8158bfc9d" }, { 4, "Jefe", 28, "what do ya want for nothing?", "0x750c783e6ab0b503eaa86e310a5db738" }, { 16, { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }, 50, { 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, }, "0x56be34521d144c88dbb8c733f0e8b3f6" }, { 25, { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 }, 50, { 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, }, "0x697eaf0aca3a3aea3a75164746ffaa79" }, { 16, { 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c }, 20, "Test With Truncation", "0x56461ef2342edc00f9bab995690efd4c" }, { 80, { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, }, 54, "Test Using Larger Than Block-Size Key - Hash Key First", "0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd" }, { 80, { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, }, 73, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", "0x6f630fad67cda0ee1fb1f562db3aa53e" }, }; for (i = 0; i < sizeof(md5tests)/sizeof(md5tests[0]); i++) { key.contents = md5tests[i].key; key.length = md5tests[i].key_len; in.data = md5tests[i].data; in.length = md5tests[i].data_len; out.data = outbuf; out.length = 20; printf("\nTest #%d:\n", i+1); err = hmac1(&krb5int_hash_md5, &key, &in, &out); if (err) { com_err(whoami, err, "computing hmac"); exit(1); } k5_buf_init_fixed(&buf, stroutbuf, sizeof(stroutbuf)); k5_buf_add(&buf, "0x"); for (j = 0; j < out.length; j++) k5_buf_add_fmt(&buf, "%02x", 0xff & outbuf[j]); if (k5_buf_data(&buf) == NULL) abort(); if (strcmp(stroutbuf, md5tests[i].hexdigest)) { printf("*** CHECK FAILED!\n" "\tReturned: %s.\n" "\tExpected: %s.\n", stroutbuf, md5tests[i].hexdigest); lose++; } else printf("Matches expected result.\n"); } /* Do again with SHA-1 tests.... */ if (lose) { printf("%d failures; exiting.\n", lose); exit(1); } }