WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, struct policy_handle *handle, const char *value_name, uint32_t offered, enum winreg_Type *type, uint32_t *needed_p, uint8_t **data_p) { NTSTATUS status; WERROR werror; uint32_t needed; uint8_t *data; struct dcerpc_binding_handle *b = cli->binding_handle; data = talloc_zero_array(mem_ctx, uint8_t, offered); W_ERROR_HAVE_NO_MEMORY(data); status = dcerpc_spoolss_GetPrinterData(b, mem_ctx, handle, value_name, type, data, offered, &needed, &werror); if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } if (W_ERROR_EQUAL(werror, WERR_MORE_DATA)) { offered = needed; data = talloc_zero_array(mem_ctx, uint8_t, offered); W_ERROR_HAVE_NO_MEMORY(data); status = dcerpc_spoolss_GetPrinterData(b, mem_ctx, handle, value_name, type, data, offered, &needed, &werror); } if (!NT_STATUS_IS_OK(status)) { return ntstatus_to_werror(status); } *data_p = data; *needed_p = needed; return werror; }
static bool test_GetPrinterData(struct torture_context *tctx, struct dcerpc_binding_handle *b, struct policy_handle *handle, const char *value_name, WERROR expected_werr, uint32_t expected_value) { NTSTATUS status; struct spoolss_GetPrinterData gpd; uint32_t needed; enum winreg_Type type; uint8_t *data = talloc_zero_array(tctx, uint8_t, 4); torture_comment(tctx, "Testing GetPrinterData(%s).\n", value_name); gpd.in.handle = handle; gpd.in.value_name = value_name; gpd.in.offered = 4; gpd.out.needed = &needed; gpd.out.type = &type; gpd.out.data = data; status = dcerpc_spoolss_GetPrinterData_r(b, tctx, &gpd); torture_assert_ntstatus_ok(tctx, status, "GetPrinterData failed."); torture_assert_werr_equal(tctx, gpd.out.result, expected_werr, "GetPrinterData did not return expected error value."); if (W_ERROR_IS_OK(expected_werr)) { uint32_t value = IVAL(data, 0); torture_assert_int_equal(tctx, value, expected_value, talloc_asprintf(tctx, "GetPrinterData for %s did not return expected value.", value_name)); } return true; }
/** Initialize a way for multiple threads to log to one or more files. * * @param ctx The talloc context * @return the new context, or NULL on error. */ fr_logfile_t *fr_logfile_init(TALLOC_CTX *ctx) { fr_logfile_t *lf; lf = talloc_zero(ctx, fr_logfile_t); if (!lf) return NULL; lf->entries = talloc_zero_array(lf, fr_logfile_entry_t, 64); if (!lf->entries) { talloc_free(lf); return NULL; } #ifdef HAVE_PTHREAD_H if (pthread_mutex_init(&lf->mutex, NULL) != 0) { talloc_free(lf); return NULL; } #endif lf->max_entries = 64; talloc_set_destructor(lf, _logfile_free); return lf; }
int daemon_check_srvids(struct ctdb_context *ctdb, TDB_DATA indata, TDB_DATA *outdata) { uint64_t *ids; int i, num_ids; uint8_t *results; if ((indata.dsize % sizeof(uint64_t)) != 0) { DEBUG(DEBUG_ERR, ("Bad indata in daemon_check_srvids, " "size=%d\n", (int)indata.dsize)); return -1; } ids = (uint64_t *)indata.dptr; num_ids = indata.dsize / 8; results = talloc_zero_array(outdata, uint8_t, (num_ids+7)/8); if (results == NULL) { DEBUG(DEBUG_ERR, ("talloc failed in daemon_check_srvids\n")); return -1; } for (i=0; i<num_ids; i++) { if (srvid_exists(ctdb->srv, ids[i]) == 0) { results[i/8] |= (1 << (i%8)); } } outdata->dptr = (uint8_t *)results; outdata->dsize = talloc_get_size(results); return 0; }
/* * this is the entry point if SMB2 is selected via * the SMB negprot and the given dialect. */ static void reply_smb20xx(struct smb_request *req, uint16_t dialect) { uint8_t *smb2_inpdu; uint8_t *smb2_hdr; uint8_t *smb2_body; uint8_t *smb2_dyn; size_t len = SMB2_HDR_BODY + 0x24 + 2; smb2_inpdu = talloc_zero_array(talloc_tos(), uint8_t, len); if (smb2_inpdu == NULL) { DEBUG(0, ("Could not push spnego blob\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } smb2_hdr = smb2_inpdu; smb2_body = smb2_hdr + SMB2_HDR_BODY; smb2_dyn = smb2_body + 0x24; SIVAL(smb2_hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC); SIVAL(smb2_hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY); SSVAL(smb2_body, 0x00, 0x0024); /* struct size */ SSVAL(smb2_body, 0x02, 0x0001); /* dialect count */ SSVAL(smb2_dyn, 0x00, dialect); req->outbuf = NULL; smbd_smb2_process_negprot(req->xconn, 0, smb2_inpdu, len); return; }
/* * this is the entry point if SMB2 is selected via * the SMB negprot */ void reply_smb2002(struct smb_request *req, uint16_t choice) { uint8_t *smb2_inbuf; uint8_t *smb2_hdr; uint8_t *smb2_body; uint8_t *smb2_dyn; size_t len = 4 + SMB2_HDR_BODY + 0x24 + 2; smb2_inbuf = talloc_zero_array(talloc_tos(), uint8_t, len); if (smb2_inbuf == NULL) { DEBUG(0, ("Could not push spnego blob\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } smb2_hdr = smb2_inbuf + 4; smb2_body = smb2_hdr + SMB2_HDR_BODY; smb2_dyn = smb2_body + 0x24; SIVAL(smb2_hdr, SMB2_HDR_PROTOCOL_ID, SMB2_MAGIC); SIVAL(smb2_hdr, SMB2_HDR_LENGTH, SMB2_HDR_BODY); SSVAL(smb2_body, 0x00, 0x0024); /* struct size */ SSVAL(smb2_body, 0x02, 0x0001); /* dialect count */ SSVAL(smb2_dyn, 0x00, 0x0202); /* dialect 2.002 */ req->outbuf = NULL; smbd_smb2_first_negprot(smbd_server_conn, smb2_inbuf, len); return; }
static TID_SRVR_BLK *tr_msg_decode_servers(void * ctx, json_t *jservers, size_t *out_len) { TID_SRVR_BLK *servers = NULL; json_t *jsrvr; size_t i, num_servers; num_servers = json_array_size(jservers); tr_debug("tr_msg_decode_servers(): Number of servers = %u.", (unsigned) num_servers); if (0 == num_servers) { tr_debug("tr_msg_decode_servers(): Server array is empty."); return NULL; } servers = talloc_zero_array(ctx, TID_SRVR_BLK, num_servers); for (i = 0; i < num_servers; i++) { jsrvr = json_array_get(jservers, i); if (0 != tr_msg_decode_one_server(jsrvr, &servers[i])) { talloc_free(servers); return NULL; } } *out_len = num_servers; return servers; }
/** Initialize a way for multiple threads to log to one or more files. * * @param ctx The talloc context * @param max_entries Max file descriptors to cache, and manage locks for. * @param max_idle Maximum time a file descriptor can be idle before it's closed. * @return the new context, or NULL on error. */ exfile_t *exfile_init(TALLOC_CTX *ctx, uint32_t max_entries, uint32_t max_idle) { exfile_t *ef; ef = talloc_zero(ctx, exfile_t); if (!ef) return NULL; ef->entries = talloc_zero_array(ef, exfile_entry_t, max_entries); if (!ef->entries) { talloc_free(ef); return NULL; } #ifdef HAVE_PTHREAD_H if (pthread_mutex_init(&ef->mutex, NULL) != 0) { talloc_free(ef); return NULL; } #endif ef->max_entries = max_entries; ef->max_idle = max_idle; talloc_set_destructor(ef, _exfile_free); return ef; }
/* * compose EAP reply packet in EAP-Message attr of RADIUS. If * EAP exceeds 253, frame it in multiple EAP-Message attrs. */ int eap_basic_compose(RADIUS_PACKET *packet, eap_packet_t *reply) { VALUE_PAIR *vp; eap_packet_raw_t *eap_packet; int rcode; if (eap_wireformat(reply) == EAP_INVALID) { return RLM_MODULE_INVALID; } eap_packet = (eap_packet_raw_t *)reply->packet; fr_pair_delete_by_num(&(packet->vps), 0, PW_EAP_MESSAGE, TAG_ANY); vp = eap_packet2vp(packet, eap_packet); if (!vp) return RLM_MODULE_INVALID; fr_pair_add(&(packet->vps), vp); /* * EAP-Message is always associated with * Message-Authenticator but not vice-versa. * * Don't add a Message-Authenticator if it's already * there. */ vp = fr_pair_find_by_num(packet->vps, 0, PW_MESSAGE_AUTHENTICATOR, TAG_ANY); if (!vp) { vp = fr_pair_afrom_num(packet, 0, PW_MESSAGE_AUTHENTICATOR); vp->vp_length = AUTH_VECTOR_LEN; vp->vp_octets = talloc_zero_array(vp, uint8_t, vp->vp_length); fr_pair_add(&(packet->vps), vp); } /* Set request reply code, but only if it's not already set. */ rcode = RLM_MODULE_OK; if (!packet->code) switch (reply->code) { case PW_EAP_RESPONSE: case PW_EAP_SUCCESS: packet->code = PW_CODE_ACCESS_ACCEPT; rcode = RLM_MODULE_HANDLED; break; case PW_EAP_FAILURE: packet->code = PW_CODE_ACCESS_REJECT; rcode = RLM_MODULE_REJECT; break; case PW_EAP_REQUEST: packet->code = PW_CODE_ACCESS_CHALLENGE; rcode = RLM_MODULE_HANDLED; break; default: /* Should never enter here */ ERROR("rlm_eap: reply code %d is unknown, Rejecting the request.", reply->code); packet->code = PW_CODE_ACCESS_REJECT; break; } return rcode; }
/* * Convert a buffer to a CSV entry */ static rlm_csv_entry_t *file2csv(CONF_SECTION *conf, rlm_csv_t *inst, int lineno, char *buffer) { rlm_csv_entry_t *e; int i; char *p, *q; e = (rlm_csv_entry_t *) talloc_zero_array(inst->tree, uint8_t, sizeof(*e) + inst->used_fields + sizeof(e->data[0])); if (!e) { cf_log_err_cs(conf, "Out of memory"); return NULL; } for (p = buffer, i = 0; p != NULL; p = q, i++) { if (!buf2entry(inst, p, &q)) { cf_log_err_cs(conf, "Malformed entry in file %s line %d", inst->filename, lineno); return NULL; } if (q) *(q++) = '\0'; if (i >= inst->num_fields) { cf_log_err_cs(conf, "Too many fields at file %s line %d", inst->filename, lineno); return NULL; } /* * This is the key field. */ if (i == inst->key_field) { e->key = talloc_strdup(e, p); continue; } /* * This field is unused. Ignore it. */ if (inst->field_offsets[i] < 0) continue; e->data[inst->field_offsets[i]] = talloc_strdup(e, p); } if (i < inst->num_fields) { cf_log_err_cs(conf, "Too few fields at file %s line %d (%d < %d)", inst->filename, lineno, i, inst->num_fields); return NULL; } /* * FIXME: Allow duplicate keys later. */ if (!rbtree_insert(inst->tree, e)) { cf_log_err_cs(conf, "Failed inserting entry for filename %s line %d: duplicate entry", inst->filename, lineno); return NULL; } return e; }
/* setup a SMB packet at transport level */ struct smbcli_request *smbcli_request_setup_transport(struct smbcli_transport *transport, uint8_t command, unsigned int wct, unsigned int buflen) { struct smbcli_request *req; size_t size; size = NBT_HDR_SIZE + MIN_SMB_SIZE + wct*2 + buflen; req = talloc_zero(transport, struct smbcli_request); if (!req) { return NULL; } /* setup the request context */ req->state = SMBCLI_REQUEST_INIT; req->transport = transport; req->out.size = size; /* over allocate by a small amount */ req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; req->out.buffer = talloc_zero_array(req, uint8_t, req->out.allocated); if (!req->out.buffer) { return NULL; } req->out.hdr = req->out.buffer + NBT_HDR_SIZE; req->out.vwv = req->out.hdr + HDR_VWV; req->out.wct = wct; req->out.data = req->out.vwv + VWV(wct) + 2; req->out.data_size = buflen; req->out.ptr = req->out.data; SCVAL(req->out.hdr, HDR_WCT, wct); SSVAL(req->out.vwv, VWV(wct), buflen); memcpy(req->out.hdr, "\377SMB", 4); SCVAL(req->out.hdr,HDR_COM,command); SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES); SSVAL(req->out.hdr,HDR_FLG2, 0); /* copy the pid, uid and mid to the request */ SSVAL(req->out.hdr, HDR_PID, 0); SSVAL(req->out.hdr, HDR_UID, 0); SSVAL(req->out.hdr, HDR_MID, 0); SSVAL(req->out.hdr, HDR_TID,0); SSVAL(req->out.hdr, HDR_PIDHIGH,0); SIVAL(req->out.hdr, HDR_RCLS, 0); memset(req->out.hdr+HDR_SS_FIELD, 0, 10); return req; }
static bool torture_rpc_spoolss_access_printop_setup(struct torture_context *tctx, void **data) { struct torture_access_context *t; *data = t = talloc_zero(tctx, struct torture_access_context); t->user.num_builtin_memberships = 1; t->user.builtin_memberships = talloc_zero_array(t, uint32_t, t->user.num_builtin_memberships); t->user.builtin_memberships[0] = BUILTIN_RID_PRINT_OPERATORS; t->user.username = talloc_strdup(t, TORTURE_USER_PRINTOPGROUP); t->user.admin_rights = true; return torture_rpc_spoolss_access_setup_common(tctx, t); }
static bool open_and_sort_dir(vfs_handle_struct *handle, struct dirsort_privates *data) { unsigned int i = 0; unsigned int total_count = 0; data->number_of_entries = 0; if (get_sorted_dir_mtime(handle, data, &data->mtime) == false) { return false; } while (SMB_VFS_NEXT_READDIR(handle, data->source_directory, NULL) != NULL) { total_count++; } if (total_count == 0) { return false; } /* Open the underlying directory and count the number of entries Skip back to the beginning as we'll read it again */ SMB_VFS_NEXT_REWINDDIR(handle, data->source_directory); /* Set up an array and read the directory entries into it */ TALLOC_FREE(data->directory_list); /* destroy previous cache if needed */ data->directory_list = talloc_zero_array(data, SMB_STRUCT_DIRENT, total_count); if (!data->directory_list) { return false; } for (i = 0; i < total_count; i++) { SMB_STRUCT_DIRENT *dp = SMB_VFS_NEXT_READDIR(handle, data->source_directory, NULL); if (dp == NULL) { break; } data->directory_list[i] = *dp; } data->number_of_entries = i; /* Sort the directory entries by name */ TYPESAFE_QSORT(data->directory_list, data->number_of_entries, compare_dirent); return true; }
/* setup a trans2 reply, given the data and params sizes */ static NTSTATUS trans2_setup_reply(struct smb_trans2 *trans, uint16_t param_size, uint16_t data_size, uint8_t setup_count) { trans->out.setup_count = setup_count; if (setup_count > 0) { trans->out.setup = talloc_zero_array(trans, uint16_t, setup_count); NT_STATUS_HAVE_NO_MEMORY(trans->out.setup); } trans->out.params = data_blob_talloc(trans, NULL, param_size); if (param_size > 0) NT_STATUS_HAVE_NO_MEMORY(trans->out.params.data); trans->out.data = data_blob_talloc(trans, NULL, data_size); if (data_size > 0) NT_STATUS_HAVE_NO_MEMORY(trans->out.data.data); return NT_STATUS_OK; }
/* setup a nttrans reply, given the data and params sizes */ static NTSTATUS nttrans_setup_reply(struct nttrans_op *op, struct smb_nttrans *trans, uint32_t param_size, uint32_t data_size, uint8_t setup_count) { trans->out.setup_count = setup_count; if (setup_count != 0) { trans->out.setup = talloc_zero_array(op, uint8_t, setup_count*2); NT_STATUS_HAVE_NO_MEMORY(trans->out.setup); } trans->out.params = data_blob_talloc(op, NULL, param_size); if (param_size != 0) { NT_STATUS_HAVE_NO_MEMORY(trans->out.params.data); } trans->out.data = data_blob_talloc(op, NULL, data_size); if (data_size != 0) { NT_STATUS_HAVE_NO_MEMORY(trans->out.data.data); } return NT_STATUS_OK; }
/* test surrounding conformant array handling */ static bool test_surrounding(struct torture_context *tctx, struct dcerpc_pipe *p) { NTSTATUS status; struct echo_TestSurrounding r; ZERO_STRUCT(r); r.in.data = talloc(tctx, struct echo_Surrounding); r.in.data->x = 20; r.in.data->surrounding = talloc_zero_array(tctx, uint16_t, r.in.data->x); r.out.data = talloc(tctx, struct echo_Surrounding); status = dcerpc_echo_TestSurrounding(p, tctx, &r); torture_assert_ntstatus_ok(tctx, status, "TestSurrounding failed"); torture_assert(tctx, r.out.data->x == 2 * r.in.data->x, "TestSurrounding did not make the array twice as large"); return true; }
/* Return an array of krb5_enctype values */ static krb5_error_code ms_suptypes_to_ietf_enctypes(TALLOC_CTX *mem_ctx, uint32_t enctype_bitmap, krb5_enctype **enctypes) { unsigned int i, j = 0; *enctypes = talloc_zero_array(mem_ctx, krb5_enctype, (8 * sizeof(enctype_bitmap)) + 1); if (!*enctypes) { return ENOMEM; } for (i = 0; i < (8 * sizeof(enctype_bitmap)); i++) { uint32_t bit_value = (1 << i) & enctype_bitmap; if (bit_value & enctype_bitmap) { (*enctypes)[j] = ms_suptype_to_ietf_enctype(bit_value); if (!(*enctypes)[j]) { continue; } j++; } } (*enctypes)[j] = 0; return 0; }
WERROR hexedit_set_buf(struct hexedit *buf, const void *data, size_t sz) { TALLOC_FREE(buf->data); buf->data = talloc_zero_array(buf, uint8_t, sz); if (buf->data == NULL) { return WERR_NOT_ENOUGH_MEMORY; } if (data != NULL) { memcpy(buf->data, data, sz); } buf->len = sz; buf->alloc_size = sz; buf->cursor_x = HEX_COL1; buf->cursor_y = 0; buf->cursor_offset = 0; buf->cursor_line_offset = 0; buf->nibble = 0; return WERR_OK; }
/** Parse module's configuration section and setup destructors * */ static int module_conf_parse(module_instance_t *node, void **handle) { *handle = NULL; /* * If there is supposed to be instance data, allocate it now. * Also parse the configuration data, if required. */ if (node->entry->module->inst_size) { /* FIXME: make this rlm_config_t ?? */ *handle = talloc_zero_array(node, uint8_t, node->entry->module->inst_size); rad_assert(handle); /* * So we can see where this configuration is from * FIXME: set it to rlm_NAME_t, or some such thing */ talloc_set_name(*handle, "rlm_config_t"); if (node->entry->module->config && (cf_section_parse(node->cs, *handle, node->entry->module->config) < 0)) { cf_log_err_cs(node->cs,"Invalid configuration for module \"%s\"", node->name); talloc_free(*handle); return -1; } /* * Set the destructor. */ if (node->entry->module->detach) { talloc_set_destructor((void *) *handle, node->entry->module->detach); } } return 0; }
/** \details Test dump of a set of recipients This function: -# builds a recipient list -# dumps out the recipient list using mapidump_Recipients() \param mt pointer to the top-level mapitest structure \return true on success, otherwise false \note This currently doesn't check the results are sane, so manual inspection is required */ _PUBLIC_ bool mapitest_mapidump_recipients(struct mapitest *mt) { const char **userlist; struct SRowSet resolved; struct PropertyTagArray_r flaglist; struct SPropValue SPropValue; userlist = talloc_array(mt->mem_ctx, const char*, 3); userlist[0] = "Mr. Unresolved"; userlist[1] = "Mr/Ms. Ambiguous"; userlist[2] = "Mrs. Resolved"; resolved.cRows = 1; resolved.aRow = talloc_array(mt->mem_ctx, struct SRow, resolved.cRows); resolved.aRow[0].cValues = 0; resolved.aRow[0].lpProps = talloc_zero(mt->mem_ctx, struct SPropValue); SPropValue.ulPropTag = PR_OBJECT_TYPE; SPropValue.value.l = MAPI_MAILUSER; SRow_addprop(&(resolved.aRow[0]), SPropValue); SPropValue.ulPropTag = PR_GIVEN_NAME; SPropValue.value.lpszA = "gname"; SRow_addprop(&(resolved.aRow[0]), SPropValue); flaglist.cValues = 3; flaglist.aulPropTag = talloc_zero_array(mt->mem_ctx, uint32_t, flaglist.cValues); flaglist.aulPropTag[0] = MAPI_UNRESOLVED; flaglist.aulPropTag[1] = MAPI_AMBIGUOUS; flaglist.aulPropTag[2] = MAPI_RESOLVED; mapidump_Recipients(userlist, &resolved, &flaglist); talloc_free(flaglist.aulPropTag); return true; }
/* spoolss_GetPrinterData */ static WERROR dcesrv_spoolss_GetPrinterData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct spoolss_GetPrinterData *r) { struct ntptr_GenericHandle *handle; struct dcesrv_handle *h; WERROR status; r->out.type = talloc_zero(mem_ctx, enum winreg_Type); W_ERROR_HAVE_NO_MEMORY(r->out.type); r->out.needed = talloc_zero(mem_ctx, uint32_t); W_ERROR_HAVE_NO_MEMORY(r->out.needed); r->out.data = talloc_zero_array(mem_ctx, uint8_t, r->in.offered); W_ERROR_HAVE_NO_MEMORY(r->out.data); DCESRV_PULL_HANDLE_WERR(h, r->in.handle, DCESRV_HANDLE_ANY); handle = talloc_get_type(h->data, struct ntptr_GenericHandle); if (!handle) return WERR_BADFID; switch (handle->type) { case NTPTR_HANDLE_SERVER: status = ntptr_GetPrintServerData(handle, mem_ctx, r); break; default: status = WERR_FOOBAR; break; } W_ERROR_NOT_OK_RETURN(status); *r->out.type = SPOOLSS_BUFFER_OK(*r->out.type, REG_NONE); r->out.data = SPOOLSS_BUFFER_OK(r->out.data, r->out.data); return SPOOLSS_BUFFER_OK(WERR_OK, WERR_MORE_DATA); }
/** Create a new map proc instance * * This should be called for every map {} section in the configuration. * * @param ctx to allocate proc instance in. * @param proc resolved with #map_proc_find. * @param src template. * @param maps Head of the list of maps. * @return * - New #map_proc_inst_t on success. * - NULL on error. */ map_proc_inst_t *map_proc_instantiate(TALLOC_CTX *ctx, map_proc_t const *proc, vp_tmpl_t const *src, vp_map_t const *maps) { map_proc_inst_t *inst; inst = talloc_zero(ctx, map_proc_inst_t); inst->proc = proc; inst->src = src; inst->maps = maps; if (proc->instantiate) { if (proc->inst_size > 0) { inst->data = talloc_zero_array(inst, uint8_t, proc->inst_size); if (!inst->data) return NULL; } if (proc->instantiate(inst->data, proc->mod_inst, src, maps) < 0) { talloc_free(inst); return NULL; } } return inst; }
int compute_peer_confirm (pwd_session_t *sess, uint8_t *buf, BN_CTX *bnctx) { BIGNUM *x = NULL, *y = NULL; HMAC_CTX ctx; uint8_t *cruft = NULL; int offset, req = -1; /* * Each component of the cruft will be at most as big as the prime */ if (((cruft = talloc_zero_array(sess, uint8_t, BN_num_bytes(sess->prime))) == NULL) || ((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { DEBUG2("pwd: unable to allocate space to compute confirm!"); goto fin; } /* * commit is H(k | server_element | server_scalar | peer_element | * peer_scalar | ciphersuite) */ H_Init(&ctx); /* * Zero the memory each time because this is mod prime math and some * value may start with a few zeros and the previous one did not. * * First is k */ offset = BN_num_bytes(sess->prime) - BN_num_bytes(sess->k); BN_bn2bin(sess->k, cruft + offset); H_Update(&ctx, cruft, BN_num_bytes(sess->prime)); /* * then peer element: x, y */ if (!EC_POINT_get_affine_coordinates_GFp(sess->group, sess->peer_element, x, y, bnctx)) { DEBUG2("pwd: unable to get coordinates of peer's element"); goto fin; } memset(cruft, 0, BN_num_bytes(sess->prime)); offset = BN_num_bytes(sess->prime) - BN_num_bytes(x); BN_bn2bin(x, cruft + offset); H_Update(&ctx, cruft, BN_num_bytes(sess->prime)); memset(cruft, 0, BN_num_bytes(sess->prime)); offset = BN_num_bytes(sess->prime) - BN_num_bytes(y); BN_bn2bin(y, cruft + offset); H_Update(&ctx, cruft, BN_num_bytes(sess->prime)); /* * and peer scalar */ memset(cruft, 0, BN_num_bytes(sess->prime)); offset = BN_num_bytes(sess->order) - BN_num_bytes(sess->peer_scalar); BN_bn2bin(sess->peer_scalar, cruft + offset); H_Update(&ctx, cruft, BN_num_bytes(sess->order)); /* * then server element: x, y */ if (!EC_POINT_get_affine_coordinates_GFp(sess->group, sess->my_element, x, y, bnctx)) { DEBUG2("pwd: unable to get coordinates of server element"); goto fin; } memset(cruft, 0, BN_num_bytes(sess->prime)); offset = BN_num_bytes(sess->prime) - BN_num_bytes(x); BN_bn2bin(x, cruft + offset); H_Update(&ctx, cruft, BN_num_bytes(sess->prime)); memset(cruft, 0, BN_num_bytes(sess->prime)); offset = BN_num_bytes(sess->prime) - BN_num_bytes(y); BN_bn2bin(y, cruft + offset); H_Update(&ctx, cruft, BN_num_bytes(sess->prime)); /* * and server scalar */ memset(cruft, 0, BN_num_bytes(sess->prime)); offset = BN_num_bytes(sess->order) - BN_num_bytes(sess->my_scalar); BN_bn2bin(sess->my_scalar, cruft + offset); H_Update(&ctx, cruft, BN_num_bytes(sess->order)); /* * finally, ciphersuite */ H_Update(&ctx, (uint8_t *)&sess->ciphersuite, sizeof(sess->ciphersuite)); H_Final(&ctx, buf); req = 0; fin: if (cruft != NULL) { talloc_free(cruft); } BN_free(x); BN_free(y); return req; }
int compute_password_element (pwd_session_t *sess, uint16_t grp_num, char *password, int password_len, char *id_server, int id_server_len, char *id_peer, int id_peer_len, uint32_t *token) { BIGNUM *x_candidate = NULL, *rnd = NULL, *cofactor = NULL; HMAC_CTX ctx; uint8_t pwe_digest[SHA256_DIGEST_LENGTH], *prfbuf = NULL, ctr; int nid, is_odd, primebitlen, primebytelen, ret = 0; switch (grp_num) { /* from IANA registry for IKE D-H groups */ case 19: nid = NID_X9_62_prime256v1; break; case 20: nid = NID_secp384r1; break; case 21: nid = NID_secp521r1; break; case 25: nid = NID_X9_62_prime192v1; break; case 26: nid = NID_secp224r1; break; default: DEBUG("unknown group %d", grp_num); goto fail; } sess->pwe = NULL; sess->order = NULL; sess->prime = NULL; if ((sess->group = EC_GROUP_new_by_curve_name(nid)) == NULL) { DEBUG("unable to create EC_GROUP"); goto fail; } if (((rnd = BN_new()) == NULL) || ((cofactor = BN_new()) == NULL) || ((sess->pwe = EC_POINT_new(sess->group)) == NULL) || ((sess->order = BN_new()) == NULL) || ((sess->prime = BN_new()) == NULL) || ((x_candidate = BN_new()) == NULL)) { DEBUG("unable to create bignums"); goto fail; } if (!EC_GROUP_get_curve_GFp(sess->group, sess->prime, NULL, NULL, NULL)) { DEBUG("unable to get prime for GFp curve"); goto fail; } if (!EC_GROUP_get_order(sess->group, sess->order, NULL)) { DEBUG("unable to get order for curve"); goto fail; } if (!EC_GROUP_get_cofactor(sess->group, cofactor, NULL)) { DEBUG("unable to get cofactor for curve"); goto fail; } primebitlen = BN_num_bits(sess->prime); primebytelen = BN_num_bytes(sess->prime); if ((prfbuf = talloc_zero_array(sess, uint8_t, primebytelen)) == NULL) { DEBUG("unable to alloc space for prf buffer"); goto fail; } ctr = 0; while (1) { if (ctr > 10) { DEBUG("unable to find random point on curve for group %d, something's fishy", grp_num); goto fail; } ctr++; /* * compute counter-mode password value and stretch to prime * pwd-seed = H(token | peer-id | server-id | password | * counter) */ H_Init(&ctx); H_Update(&ctx, (uint8_t *)token, sizeof(*token)); H_Update(&ctx, (uint8_t *)id_peer, id_peer_len); H_Update(&ctx, (uint8_t *)id_server, id_server_len); H_Update(&ctx, (uint8_t *)password, password_len); H_Update(&ctx, (uint8_t *)&ctr, sizeof(ctr)); H_Final(&ctx, pwe_digest); BN_bin2bn(pwe_digest, SHA256_DIGEST_LENGTH, rnd); eap_pwd_kdf(pwe_digest, SHA256_DIGEST_LENGTH, "EAP-pwd Hunting And Pecking", strlen("EAP-pwd Hunting And Pecking"), prfbuf, primebitlen); BN_bin2bn(prfbuf, primebytelen, x_candidate); /* * eap_pwd_kdf() returns a string of bits 0..primebitlen but * BN_bin2bn will treat that string of bits as a big endian * number. If the primebitlen is not an even multiple of 8 * then excessive bits-- those _after_ primebitlen-- so now * we have to shift right the amount we masked off. */ if (primebitlen % 8) { BN_rshift(x_candidate, x_candidate, (8 - (primebitlen % 8))); } if (BN_ucmp(x_candidate, sess->prime) >= 0) { continue; } /* * need to unambiguously identify the solution, if there is * one... */ if (BN_is_odd(rnd)) { is_odd = 1; } else { is_odd = 0; } /* * solve the quadratic equation, if it's not solvable then we * don't have a point */ if (!EC_POINT_set_compressed_coordinates_GFp(sess->group, sess->pwe, x_candidate, is_odd, NULL)) { continue; } /* * If there's a solution to the equation then the point must be * on the curve so why check again explicitly? OpenSSL code * says this is required by X9.62. We're not X9.62 but it can't * hurt just to be sure. */ if (!EC_POINT_is_on_curve(sess->group, sess->pwe, NULL)) { DEBUG("EAP-pwd: point is not on curve"); continue; } if (BN_cmp(cofactor, BN_value_one())) { /* make sure the point is not in a small sub-group */ if (!EC_POINT_mul(sess->group, sess->pwe, NULL, sess->pwe, cofactor, NULL)) { DEBUG("EAP-pwd: cannot multiply generator by order"); continue; } if (EC_POINT_is_at_infinity(sess->group, sess->pwe)) { DEBUG("EAP-pwd: point is at infinity"); continue; } } /* if we got here then we have a new generator. */ break; } sess->group_num = grp_num; if (0) { fail: /* DON'T free sess, it's in handler->opaque */ ret = -1; } /* cleanliness and order.... */ BN_free(cofactor); BN_free(x_candidate); BN_free(rnd); talloc_free(prfbuf); return ret; }
// target must be initialized to zero static void ebml_parse_element(struct ebml_parse_ctx *ctx, void *target, uint8_t *data, int size, const struct ebml_elem_desc *type, int level) { assert(type->type == EBML_TYPE_SUBELEMENTS); assert(level < 8); MP_DBG(ctx, "%.*sParsing element %s\n", level, " ", type->name); char *s = target; uint8_t *end = data + size; uint8_t *p = data; int num_elems[MAX_EBML_SUBELEMENTS] = {0}; while (p < end) { uint8_t *startp = p; int len; uint32_t id = ebml_parse_id(p, end - p, &len); if (len > end - p) goto past_end_error; if (len < 0) { MP_DBG(ctx, "Error parsing subelement id\n"); goto other_error; } p += len; uint64_t length = ebml_parse_length(p, end - p, &len); if (len > end - p) goto past_end_error; if (len < 0) { MP_DBG(ctx, "Error parsing subelement length\n"); goto other_error; } p += len; int field_idx = -1; for (int i = 0; i < type->field_count; i++) if (type->fields[i].id == id) { field_idx = i; num_elems[i]++; if (num_elems[i] >= 0x70000000) { MP_ERR(ctx, "Too many EBML subelements.\n"); goto other_error; } break; } if (length > end - p) { if (field_idx >= 0 && type->fields[field_idx].desc->type != EBML_TYPE_SUBELEMENTS) { MP_DBG(ctx, "Subelement content goes " "past end of containing element\n"); goto other_error; } // Try to parse what is possible from inside this partial element ctx->has_errors = true; length = end - p; } p += length; continue; past_end_error: MP_DBG(ctx, "Subelement headers go past end of containing element\n"); other_error: ctx->has_errors = true; end = startp; break; } for (int i = 0; i < type->field_count; i++) if (num_elems[i] && type->fields[i].multiple) { char *ptr = s + type->fields[i].offset; switch (type->fields[i].desc->type) { case EBML_TYPE_SUBELEMENTS: { size_t max = 1000000000 / type->fields[i].desc->size; if (num_elems[i] > max) { MP_ERR(ctx, "Too many subelements.\n"); num_elems[i] = max; } int sz = num_elems[i] * type->fields[i].desc->size; *(generic_struct **) ptr = talloc_zero_size(ctx->talloc_ctx, sz); break; } case EBML_TYPE_UINT: *(uint64_t **) ptr = talloc_zero_array(ctx->talloc_ctx, uint64_t, num_elems[i]); break; case EBML_TYPE_SINT: *(int64_t **) ptr = talloc_zero_array(ctx->talloc_ctx, int64_t, num_elems[i]); break; case EBML_TYPE_FLOAT: *(double **) ptr = talloc_zero_array(ctx->talloc_ctx, double, num_elems[i]); break; case EBML_TYPE_STR: case EBML_TYPE_BINARY: *(struct bstr **) ptr = talloc_zero_array(ctx->talloc_ctx, struct bstr, num_elems[i]); break; case EBML_TYPE_EBML_ID: *(int32_t **) ptr = talloc_zero_array(ctx->talloc_ctx, uint32_t, num_elems[i]); break; default: abort(); } }
static REQUEST *request_setup(FILE *fp) { VALUE_PAIR *vp; REQUEST *request; vp_cursor_t cursor; /* * Create and initialize the new request. */ request = request_alloc(NULL); request->packet = rad_alloc(request, false); if (!request->packet) { ERROR("No memory"); talloc_free(request); return NULL; } request->reply = rad_alloc(request, false); if (!request->reply) { ERROR("No memory"); talloc_free(request); return NULL; } request->listener = listen_alloc(request); request->client = client_alloc(request); request->number = 0; request->master_state = REQUEST_ACTIVE; request->child_state = REQUEST_RUNNING; request->handle = NULL; request->server = talloc_typed_strdup(request, "default"); request->root = &main_config; /* * Read packet from fp */ if (readvp2(request->packet, &request->packet->vps, fp, &filedone) < 0) { fr_perror("unittest"); talloc_free(request); return NULL; } /* * Set the defaults for IPs, etc. */ request->packet->code = PW_CODE_ACCESS_REQUEST; request->packet->src_ipaddr.af = AF_INET; request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK); request->packet->src_port = 18120; request->packet->dst_ipaddr.af = AF_INET; request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK); request->packet->dst_port = 1812; /* * Copied from radclient */ #if 1 /* * Fix up Digest-Attributes issues */ for (vp = fr_cursor_init(&cursor, &request->packet->vps); vp; vp = fr_cursor_next(&cursor)) { /* * Double quoted strings get marked up as xlat expansions, * but we don't support that here. */ if (vp->type == VT_XLAT) { vp->vp_strvalue = vp->value.xlat; vp->value.xlat = NULL; vp->type = VT_DATA; } if (!vp->da->vendor) switch (vp->da->attr) { default: break; /* * Allow it to set the packet type in * the attributes read from the file. */ case PW_PACKET_TYPE: request->packet->code = vp->vp_integer; break; case PW_PACKET_DST_PORT: request->packet->dst_port = (vp->vp_integer & 0xffff); break; case PW_PACKET_DST_IP_ADDRESS: request->packet->dst_ipaddr.af = AF_INET; request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; break; case PW_PACKET_DST_IPV6_ADDRESS: request->packet->dst_ipaddr.af = AF_INET6; request->packet->dst_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr; break; case PW_PACKET_SRC_PORT: request->packet->src_port = (vp->vp_integer & 0xffff); break; case PW_PACKET_SRC_IP_ADDRESS: request->packet->src_ipaddr.af = AF_INET; request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; break; case PW_PACKET_SRC_IPV6_ADDRESS: request->packet->src_ipaddr.af = AF_INET6; request->packet->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr; break; case PW_CHAP_PASSWORD: { int i, already_hex = 0; /* * If it's 17 octets, it *might* be already encoded. * Or, it might just be a 17-character password (maybe UTF-8) * Check it for non-printable characters. The odds of ALL * of the characters being 32..255 is (1-7/8)^17, or (1/8)^17, * or 1/(2^51), which is pretty much zero. */ if (vp->length == 17) { for (i = 0; i < 17; i++) { if (vp->vp_octets[i] < 32) { already_hex = 1; break; } } } /* * Allow the user to specify ASCII or hex CHAP-Password */ if (!already_hex) { uint8_t *p; size_t len, len2; len = len2 = vp->length; if (len2 < 17) len2 = 17; p = talloc_zero_array(vp, uint8_t, len2); memcpy(p, vp->vp_strvalue, len); rad_chap_encode(request->packet, p, fr_rand() & 0xff, vp); vp->vp_octets = p; vp->length = 17; } } break; case PW_DIGEST_REALM: case PW_DIGEST_NONCE: case PW_DIGEST_METHOD: case PW_DIGEST_URI: case PW_DIGEST_QOP: case PW_DIGEST_ALGORITHM: case PW_DIGEST_BODY_DIGEST: case PW_DIGEST_CNONCE: case PW_DIGEST_NONCE_COUNT: case PW_DIGEST_USER_NAME: /* overlapping! */ { DICT_ATTR const *da; uint8_t *p, *q; p = talloc_array(vp, uint8_t, vp->length + 2); memcpy(p + 2, vp->vp_octets, vp->length); p[0] = vp->da->attr - PW_DIGEST_REALM + 1; vp->length += 2; p[1] = vp->length; da = dict_attrbyvalue(PW_DIGEST_ATTRIBUTES, 0); rad_assert(da != NULL); vp->da = da; /* * Re-do pairmemsteal ourselves, * because we play games with * vp->da, and pairmemsteal goes * to GREAT lengths to sanitize * and fix and change and * double-check the various * fields. */ memcpy(&q, &vp->vp_octets, sizeof(q)); talloc_free(q); vp->vp_octets = talloc_steal(vp, p); vp->type = VT_DATA; VERIFY_VP(vp); } break; } } /* loop over the VP's we read in */ #endif if (debug_flag) { for (vp = fr_cursor_init(&cursor, &request->packet->vps); vp; vp = fr_cursor_next(&cursor)) { /* * Take this opportunity to verify all the VALUE_PAIRs are still valid. */ if (!talloc_get_type(vp, VALUE_PAIR)) { ERROR("Expected VALUE_PAIR pointer got \"%s\"", talloc_get_name(vp)); fr_log_talloc_report(vp); rad_assert(0); } vp_print(fr_log_fp, vp); } fflush(fr_log_fp); } /* * FIXME: set IPs, etc. */ request->packet->code = PW_CODE_ACCESS_REQUEST; request->packet->src_ipaddr.af = AF_INET; request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK); request->packet->src_port = 18120; request->packet->dst_ipaddr.af = AF_INET; request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK); request->packet->dst_port = 1812; /* * Build the reply template from the request. */ request->reply->sockfd = request->packet->sockfd; request->reply->dst_ipaddr = request->packet->src_ipaddr; request->reply->src_ipaddr = request->packet->dst_ipaddr; request->reply->dst_port = request->packet->src_port; request->reply->src_port = request->packet->dst_port; request->reply->id = request->packet->id; request->reply->code = 0; /* UNKNOWN code */ memcpy(request->reply->vector, request->packet->vector, sizeof(request->reply->vector)); request->reply->vps = NULL; request->reply->data = NULL; request->reply->data_len = 0; /* * Debugging */ request->log.lvl = debug_flag; request->log.func = vradlog_request; request->username = pairfind(request->packet->vps, PW_USER_NAME, 0, TAG_ANY); request->password = pairfind(request->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY); return request; }
static void store_records(struct ctdb_context *ctdb, struct event_context *ev) { TDB_DATA key, data; struct ctdb_db_context *ctdb_db; TALLOC_CTX *tmp_ctx = talloc_new(ctdb); int ret; struct ctdb_record_handle *h; uint32_t i=0; ctdb_db = ctdb_db_handle(ctdb, "test.tdb"); srandom(time(NULL) ^ getpid()); start_timer(); printf("working with %d records\n", num_records); while (1) { unsigned r = random() % num_records; key.dptr = (uint8_t *)&r; key.dsize = sizeof(r); h = ctdb_fetch_lock(ctdb_db, tmp_ctx, key, &data); if (h == NULL) { printf("Failed to fetch record '%s' on node %d\n", (const char *)key.dptr, ctdb_get_pnn(ctdb)); talloc_free(tmp_ctx); return; } if (random() % 100 < delete_pct) { data.dptr = NULL; data.dsize = 0; } else { data.dptr = talloc_zero_size(h, data.dsize + sizeof(r)); data.dsize += sizeof(r); } ret = ctdb_record_store(h, data); if (ret != 0) { printf("Failed to store record\n"); } if (data.dptr == NULL && data.dsize == 0) { struct ctdb_control_schedule_for_deletion *dd; TDB_DATA indata; int32_t status; indata.dsize = offsetof(struct ctdb_control_schedule_for_deletion, key) + key.dsize; indata.dptr = talloc_zero_array(ctdb, uint8_t, indata.dsize); if (indata.dptr == NULL) { printf("out of memory\n"); exit(1); } dd = (struct ctdb_control_schedule_for_deletion *)(void *)indata.dptr; dd->db_id = ctdb_db->db_id; dd->hdr = *ctdb_header_from_record_handle(h); dd->keylen = key.dsize; memcpy(dd->key, key.dptr, key.dsize); ret = ctdb_control(ctdb, CTDB_CURRENT_NODE, ctdb_db->db_id, CTDB_CONTROL_SCHEDULE_FOR_DELETION, 0, /* flags */ indata, NULL, /* mem_ctx */ NULL, /* outdata */ &status, NULL, /* timeout : NULL == wait forever */ NULL); /* error message */ talloc_free(indata.dptr); if (ret != 0 || status != 0) { DEBUG(DEBUG_ERR, (__location__ " Error sending " "SCHEDULE_FOR_DELETION " "control.\n")); } } talloc_free(h); if (i % 1000 == 0) { printf("%7.0f recs/second %u total\r", 1000.0 / end_timer(), i); fflush(stdout); start_timer(); } i++; } talloc_free(tmp_ctx); }
/* setup a chained reply in req->out with the given word count and initial data buffer size. */ NTSTATUS smbcli_chained_request_setup(struct smbcli_request *req, uint8_t command, unsigned int wct, size_t buflen) { size_t wct_ofs; size_t size; /* * here we only support one chained command * If someone needs longer chains, the low * level code should be used directly. */ if (req->subreqs[0] != NULL) { return NT_STATUS_INVALID_PARAMETER_MIX; } if (req->subreqs[1] != NULL) { return NT_STATUS_INVALID_PARAMETER_MIX; } req->subreqs[0] = smbcli_transport_setup_subreq(req); if (req->subreqs[0] == NULL) { return NT_STATUS_NO_MEMORY; } wct_ofs = smb1cli_req_wct_ofs(req->subreqs, 1); size = NBT_HDR_SIZE + wct_ofs + 1 + VWV(wct) + 2 + buflen; req->out.size = size; /* over allocate by a small amount */ req->out.allocated = req->out.size + REQ_OVER_ALLOCATION; req->out.buffer = talloc_zero_array(req, uint8_t, req->out.allocated); if (!req->out.buffer) { return NT_STATUS_NO_MEMORY; } req->out.hdr = req->out.buffer + NBT_HDR_SIZE; req->out.vwv = req->out.hdr + wct_ofs; req->out.wct = wct; req->out.data = req->out.vwv + VWV(wct) + 2; req->out.data_size = buflen; req->out.ptr = req->out.data; SCVAL(req->out.hdr, HDR_WCT, wct); SSVAL(req->out.vwv, VWV(wct), buflen); memcpy(req->out.hdr, "\377SMB", 4); SCVAL(req->out.hdr,HDR_COM,command); SCVAL(req->out.hdr,HDR_FLG, FLAG_CASELESS_PATHNAMES); SSVAL(req->out.hdr,HDR_FLG2, 0); /* copy the pid, uid and mid to the request */ SSVAL(req->out.hdr, HDR_PID, 0); SSVAL(req->out.hdr, HDR_UID, 0); SSVAL(req->out.hdr, HDR_MID, 0); SSVAL(req->out.hdr, HDR_TID,0); SSVAL(req->out.hdr, HDR_PIDHIGH,0); SIVAL(req->out.hdr, HDR_RCLS, 0); memset(req->out.hdr+HDR_SS_FIELD, 0, 10); if (req->session != NULL) { SSVAL(req->out.hdr, HDR_FLG2, req->session->flags2); SSVAL(req->out.hdr, HDR_PID, req->session->pid & 0xFFFF); SSVAL(req->out.hdr, HDR_PIDHIGH, req->session->pid >> 16); SSVAL(req->out.hdr, HDR_UID, req->session->vuid); }
static int mod_authenticate (void *arg, eap_handler_t *handler) { pwd_session_t *pwd_session; pwd_hdr *hdr; pwd_id_packet *id; eap_packet_t *response; REQUEST *request, *fake; VALUE_PAIR *pw, *vp; EAP_DS *eap_ds; int len, ret = 0; eap_pwd_t *inst = (eap_pwd_t *)arg; uint16_t offset; uint8_t exch, *buf, *ptr, msk[MSK_EMSK_LEN], emsk[MSK_EMSK_LEN]; uint8_t peer_confirm[SHA256_DIGEST_LENGTH]; BIGNUM *x = NULL, *y = NULL; if ((!handler) || ((eap_ds = handler->eap_ds) == NULL) || (!inst)) { return 0; } pwd_session = (pwd_session_t *)handler->opaque; request = handler->request; response = handler->eap_ds->response; hdr = (pwd_hdr *)response->type.data; buf = hdr->data; len = response->type.length - sizeof(pwd_hdr); /* * see if we're fragmenting, if so continue until we're done */ if (pwd_session->out_buf_pos) { if (len) { RDEBUG2("pwd got something more than an ACK for a fragment"); } return send_pwd_request(pwd_session, eap_ds); } /* * the first fragment will have a total length, make a * buffer to hold all the fragments */ if (EAP_PWD_GET_LENGTH_BIT(hdr)) { if (pwd_session->in_buf) { RDEBUG2("pwd already alloced buffer for fragments"); return 0; } pwd_session->in_buf_len = ntohs(buf[0] * 256 | buf[1]); if ((pwd_session->in_buf = talloc_zero_array(pwd_session, uint8_t, pwd_session->in_buf_len)) == NULL) { RDEBUG2("pwd cannot allocate %d buffer to hold fragments", pwd_session->in_buf_len); return 0; } memset(pwd_session->in_buf, 0, pwd_session->in_buf_len); pwd_session->in_buf_pos = 0; buf += sizeof(uint16_t); len -= sizeof(uint16_t); } /* * all fragments, including the 1st will have the M(ore) bit set, * buffer those fragments! */ if (EAP_PWD_GET_MORE_BIT(hdr)) { rad_assert(pwd_session->in_buf != NULL); if ((pwd_session->in_buf_pos + len) > pwd_session->in_buf_len) { RDEBUG2("pwd will not overflow a fragment buffer. Nope, not prudent."); return 0; } memcpy(pwd_session->in_buf + pwd_session->in_buf_pos, buf, len); pwd_session->in_buf_pos += len; /* * send back an ACK for this fragment */ exch = EAP_PWD_GET_EXCHANGE(hdr); eap_ds->request->code = PW_EAP_REQUEST; eap_ds->request->type.num = PW_EAP_PWD; eap_ds->request->type.length = sizeof(pwd_hdr); if ((eap_ds->request->type.data = talloc_array(eap_ds->request, uint8_t, sizeof(pwd_hdr))) == NULL) { return 0; } hdr = (pwd_hdr *)eap_ds->request->type.data; EAP_PWD_SET_EXCHANGE(hdr, exch); return 1; } if (pwd_session->in_buf) { /* * the last fragment... */ if ((pwd_session->in_buf_pos + len) > pwd_session->in_buf_len) { RDEBUG2("pwd will not overflow a fragment buffer. Nope, not prudent."); return 0; } memcpy(pwd_session->in_buf + pwd_session->in_buf_pos, buf, len); buf = pwd_session->in_buf; len = pwd_session->in_buf_len; } switch (pwd_session->state) { case PWD_STATE_ID_REQ: if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_ID) { RDEBUG2("pwd exchange is incorrect: not ID"); return 0; } id = (pwd_id_packet *)buf; if ((id->prf != EAP_PWD_DEF_PRF) || (id->random_function != EAP_PWD_DEF_RAND_FUN) || (id->prep != EAP_PWD_PREP_NONE) || (memcmp(id->token, (char *)&pwd_session->token, 4)) || (id->group_num != ntohs(pwd_session->group_num))) { RDEBUG2("pwd id response is invalid"); return 0; } /* * we've agreed on the ciphersuite, record it... */ ptr = (uint8_t *)&pwd_session->ciphersuite; memcpy(ptr, (char *)&id->group_num, sizeof(uint16_t)); ptr += sizeof(uint16_t); *ptr = EAP_PWD_DEF_RAND_FUN; ptr += sizeof(uint8_t); *ptr = EAP_PWD_DEF_PRF; pwd_session->peer_id_len = len - sizeof(pwd_id_packet); if (pwd_session->peer_id_len >= sizeof(pwd_session->peer_id)) { RDEBUG2("pwd id response is malformed"); return 0; } memcpy(pwd_session->peer_id, id->identity, pwd_session->peer_id_len); pwd_session->peer_id[pwd_session->peer_id_len] = '\0'; /* * make fake request to get the password for the usable ID */ if ((fake = request_alloc_fake(handler->request)) == NULL) { RDEBUG("pwd unable to create fake request!"); return 0; } fake->username = pairmake_packet("User-Name", "", T_OP_EQ); if (!fake->username) { RDEBUG("pwd unanable to create value pair for username!"); request_free(&fake); return 0; } memcpy(fake->username->vp_strvalue, pwd_session->peer_id, pwd_session->peer_id_len); fake->username->length = pwd_session->peer_id_len; fake->username->vp_strvalue[fake->username->length] = 0; if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER, 0, TAG_ANY)) != NULL) { fake->server = vp->vp_strvalue; } else if (inst->conf->virtual_server) { fake->server = inst->conf->virtual_server; } /* else fake->server == request->server */ if ((debug_flag > 0) && fr_log_fp) { RDEBUG("Sending tunneled request"); debug_pair_list(fake->packet->vps); fprintf(fr_log_fp, "server %s {\n", (!fake->server) ? "" : fake->server); } /* * Call authorization recursively, which will * get the password. */ process_authorize(0, fake); /* * Note that we don't do *anything* with the reply * attributes. */ if ((debug_flag > 0) && fr_log_fp) { fprintf(fr_log_fp, "} # server %s\n", (!fake->server) ? "" : fake->server); RDEBUG("Got tunneled reply code %d", fake->reply->code); debug_pair_list(fake->reply->vps); } if ((pw = pairfind(fake->config_items, PW_CLEARTEXT_PASSWORD, 0, TAG_ANY)) == NULL) { DEBUG2("failed to find password for %s to do pwd authentication", pwd_session->peer_id); request_free(&fake); return 0; } if (compute_password_element(pwd_session, pwd_session->group_num, pw->data.strvalue, strlen(pw->data.strvalue), inst->conf->server_id, strlen(inst->conf->server_id), pwd_session->peer_id, strlen(pwd_session->peer_id), &pwd_session->token)) { DEBUG2("failed to obtain password element :-("); request_free(&fake); return 0; } request_free(&fake); /* * compute our scalar and element */ if (compute_scalar_element(pwd_session, inst->bnctx)) { DEBUG2("failed to compute server's scalar and element"); return 0; } if (((x = BN_new()) == NULL) || ((y = BN_new()) == NULL)) { DEBUG2("server point allocation failed"); return 0; } /* * element is a point, get both coordinates: x and y */ if (!EC_POINT_get_affine_coordinates_GFp(pwd_session->group, pwd_session->my_element, x, y, inst->bnctx)) { DEBUG2("server point assignment failed"); BN_free(x); BN_free(y); return 0; } /* * construct request */ pwd_session->out_buf_len = BN_num_bytes(pwd_session->order) + (2 * BN_num_bytes(pwd_session->prime)); if ((pwd_session->out_buf = talloc_array(pwd_session, uint8_t, pwd_session->out_buf_len)) == NULL) { return 0; } memset(pwd_session->out_buf, 0, pwd_session->out_buf_len); ptr = pwd_session->out_buf; offset = BN_num_bytes(pwd_session->prime) - BN_num_bytes(x); BN_bn2bin(x, ptr + offset); ptr += BN_num_bytes(pwd_session->prime); offset = BN_num_bytes(pwd_session->prime) - BN_num_bytes(y); BN_bn2bin(y, ptr + offset); ptr += BN_num_bytes(pwd_session->prime); offset = BN_num_bytes(pwd_session->order) - BN_num_bytes(pwd_session->my_scalar); BN_bn2bin(pwd_session->my_scalar, ptr + offset); pwd_session->state = PWD_STATE_COMMIT; ret = send_pwd_request(pwd_session, eap_ds); break; case PWD_STATE_COMMIT: if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_COMMIT) { RDEBUG2("pwd exchange is incorrect: not commit!"); return 0; } /* * process the peer's commit and generate the shared key, k */ if (process_peer_commit(pwd_session, buf, inst->bnctx)) { RDEBUG2("failed to process peer's commit"); return 0; } /* * compute our confirm blob */ if (compute_server_confirm(pwd_session, pwd_session->my_confirm, inst->bnctx)) { ERROR("rlm_eap_pwd: failed to compute confirm!"); return 0; } /* * construct a response...which is just our confirm blob */ pwd_session->out_buf_len = SHA256_DIGEST_LENGTH; if ((pwd_session->out_buf = talloc_array(pwd_session, uint8_t, pwd_session->out_buf_len)) == NULL) { return 0; } memset(pwd_session->out_buf, 0, pwd_session->out_buf_len); memcpy(pwd_session->out_buf, pwd_session->my_confirm, SHA256_DIGEST_LENGTH); pwd_session->state = PWD_STATE_CONFIRM; ret = send_pwd_request(pwd_session, eap_ds); break; case PWD_STATE_CONFIRM: if (EAP_PWD_GET_EXCHANGE(hdr) != EAP_PWD_EXCH_CONFIRM) { RDEBUG2("pwd exchange is incorrect: not commit!"); return 0; } if (compute_peer_confirm(pwd_session, peer_confirm, inst->bnctx)) { RDEBUG2("pwd exchange cannot compute peer's confirm"); return 0; } if (memcmp(peer_confirm, buf, SHA256_DIGEST_LENGTH)) { RDEBUG2("pwd exchange fails: peer confirm is incorrect!"); return 0; } if (compute_keys(pwd_session, peer_confirm, msk, emsk)) { RDEBUG2("pwd exchange cannot generate (E)MSK!"); return 0; } eap_ds->request->code = PW_EAP_SUCCESS; /* * return the MSK (in halves) */ eap_add_reply(handler->request, "MS-MPPE-Recv-Key", msk, MPPE_KEY_LEN); eap_add_reply(handler->request, "MS-MPPE-Send-Key", msk+MPPE_KEY_LEN, MPPE_KEY_LEN); ret = 1; break; default: RDEBUG2("unknown PWD state"); return 0; } /* * we processed the buffered fragments, get rid of them */ if (pwd_session->in_buf) { talloc_free(pwd_session->in_buf); pwd_session->in_buf = NULL; } return ret; }
static int eap_pwd_initiate (void *instance, eap_handler_t *handler) { pwd_session_t *pwd_session; eap_pwd_t *inst = (eap_pwd_t *)instance; VALUE_PAIR *vp; pwd_id_packet *pack; if (!inst || !handler) { ERROR("rlm_eap_pwd: initiate, NULL data provided"); return -1; } /* * make sure the server's been configured properly */ if (!inst->conf->server_id) { ERROR("rlm_eap_pwd: server ID is not configured!"); return -1; } switch (inst->conf->group) { case 19: case 20: case 21: case 25: case 26: break; default: ERROR("rlm_eap_pwd: group is not supported!"); return -1; } if ((pwd_session = talloc_zero(handler, pwd_session_t)) == NULL) { return -1; } /* * set things up so they can be free'd reliably */ pwd_session->group_num = inst->conf->group; pwd_session->private_value = NULL; pwd_session->peer_scalar = NULL; pwd_session->my_scalar = NULL; pwd_session->k = NULL; pwd_session->my_element = NULL; pwd_session->peer_element = NULL; pwd_session->group = NULL; pwd_session->pwe = NULL; pwd_session->order = NULL; pwd_session->prime = NULL; /* * figure out the MTU (basically do what eap-tls does) */ pwd_session->mtu = inst->conf->fragment_size; vp = pairfind(handler->request->packet->vps, PW_FRAMED_MTU, 0, TAG_ANY); if (vp && ((int)(vp->vp_integer - 9) < pwd_session->mtu)) { /* * 9 = 4 (EAPOL header) + 4 (EAP header) + 1 (EAP type) * * the fragmentation code deals with the included length * so we don't need to subtract that here. */ pwd_session->mtu = vp->vp_integer - 9; } pwd_session->state = PWD_STATE_ID_REQ; pwd_session->in_buf = NULL; pwd_session->out_buf_pos = 0; handler->opaque = pwd_session; handler->free_opaque = free_session; /* * construct an EAP-pwd-ID/Request */ pwd_session->out_buf_len = sizeof(pwd_id_packet) + strlen(inst->conf->server_id); if ((pwd_session->out_buf = talloc_zero_array(pwd_session, uint8_t, pwd_session->out_buf_len)) == NULL) { return -1; } pack = (pwd_id_packet *)pwd_session->out_buf; pack->group_num = htons(pwd_session->group_num); pack->random_function = EAP_PWD_DEF_RAND_FUN; pack->prf = EAP_PWD_DEF_PRF; pwd_session->token = random(); memcpy(pack->token, (char *)&pwd_session->token, 4); pack->prep = EAP_PWD_PREP_NONE; strcpy(pack->identity, inst->conf->server_id); handler->stage = AUTHENTICATE; return send_pwd_request(pwd_session, handler->eap_ds); }