/* * this code sends the success message. * * the only work to be done is the add the appropriate SEND/RECV * radius attributes derived from the MSK. * */ static int eap_sim_sendsuccess(EAP_HANDLER *handler) { unsigned char *p; struct eap_sim_server_state *ess; VALUE_PAIR **outvps; VALUE_PAIR *newvp; /* outvps is the data to the client. */ outvps= &handler->request->reply->vps; ess = (struct eap_sim_server_state *)handler->opaque; /* set the EAP_ID - new value */ newvp = paircreate(ATTRIBUTE_EAP_ID, 0, PW_TYPE_INTEGER); newvp->vp_integer = ess->sim_id++; pairreplace(outvps, newvp); p = ess->keys.msk; add_reply(outvps, "MS-MPPE-Recv-Key", p, EAPTLS_MPPE_KEY_LEN); p += EAPTLS_MPPE_KEY_LEN; add_reply(outvps, "MS-MPPE-Send-Key", p, EAPTLS_MPPE_KEY_LEN); return 1; }
int fio_net_send_cmd(int fd, uint16_t opcode, const void *buf, off_t size, uint64_t *tagptr, struct flist_head *list) { struct fio_net_cmd *cmd = NULL; size_t this_len, cur_len = 0; uint64_t tag; int ret; if (list) { assert(tagptr); tag = *tagptr = alloc_reply(*tagptr, opcode); } else tag = tagptr ? *tagptr : 0; do { this_len = size; if (this_len > FIO_SERVER_MAX_FRAGMENT_PDU) this_len = FIO_SERVER_MAX_FRAGMENT_PDU; if (!cmd || cur_len < sizeof(*cmd) + this_len) { if (cmd) free(cmd); cur_len = sizeof(*cmd) + this_len; cmd = malloc(cur_len); } fio_init_net_cmd(cmd, opcode, buf, this_len, tag); if (this_len < size) cmd->flags = __cpu_to_le32(FIO_NET_CMD_F_MORE); fio_net_cmd_crc(cmd); ret = fio_send_data(fd, cmd, sizeof(*cmd) + this_len); size -= this_len; buf += this_len; } while (!ret && size); if (list) { if (ret) free_reply(tag); else add_reply(tag, list); } if (cmd) free(cmd); return ret; }
/* * Generate keys according to RFC 2716 and add to reply */ void eaptls_gen_mppe_keys(VALUE_PAIR **reply_vps, SSL *s, const char *prf_label) { unsigned char out[4*EAPTLS_MPPE_KEY_LEN], buf[4*EAPTLS_MPPE_KEY_LEN]; unsigned char seed[64 + 2*SSL3_RANDOM_SIZE]; unsigned char *p = seed; size_t prf_size; if (!s->s3) { radlog(L_ERR, "ERROR: OpenSSL build / link incompatibility detected"); return; } prf_size = strlen(prf_label); memcpy(p, prf_label, prf_size); p += prf_size; memcpy(p, s->s3->client_random, SSL3_RANDOM_SIZE); p += SSL3_RANDOM_SIZE; prf_size += SSL3_RANDOM_SIZE; memcpy(p, s->s3->server_random, SSL3_RANDOM_SIZE); prf_size += SSL3_RANDOM_SIZE; PRF(s->session->master_key, s->session->master_key_length, seed, prf_size, out, buf, sizeof(out)); p = out; add_reply(reply_vps, "MS-MPPE-Recv-Key", p, EAPTLS_MPPE_KEY_LEN); p += EAPTLS_MPPE_KEY_LEN; add_reply(reply_vps, "MS-MPPE-Send-Key", p, EAPTLS_MPPE_KEY_LEN); add_reply(reply_vps, "EAP-MSK", out, 64); add_reply(reply_vps, "EAP-EMSK", out + 64, 64); }
static int build_ressources_reply(t_conf *conf, void *buffer, int max_len) { struct dns_hdr *hdr; t_list *list; void *where; char buffer2[MAX_REQ_LEN]; hdr = buffer; hdr->ra = 1; hdr->qr = 1; if (!(where = jump_end_query(buffer, GET_16(&hdr->qdcount), max_len))) return (-1); for (list = conf->ressources; list; list = list->next) { base64_encode(list->data, buffer2, (strchr(list->data, ':') - list->data)); where = add_reply(hdr, where, TYPE_KEY, buffer2); } return (where - buffer); }
/* * If 'list' is non-NULL, then allocate and store the sent command for * later verification. */ int fio_net_send_simple_cmd(int sk, uint16_t opcode, uint64_t tag, struct flist_head *list) { int ret; if (list) tag = alloc_reply(tag, opcode); ret = fio_net_send_simple_stack_cmd(sk, opcode, tag); if (ret) { if (list) free_reply(tag); return ret; } if (list) add_reply(tag, list); return 0; }
int build_error_reply(t_conf *conf, void *req, int max_len, char *error) { struct dns_hdr *hdr; void *where; t_packet *packet; char buffer[BASE64_SIZE(MAX_ERROR_SIZE) + PACKET_LEN]; char buffer2[BASE64_SIZE(MAX_ERROR_SIZE) + PACKET_LEN]; int len; hdr = req; hdr->ra = 1; hdr->qr = 1; if (!(where = jump_end_query(req, GET_16(&hdr->qdcount), max_len))) return (-1); packet = (t_packet *) memset(buffer, 0, PACKET_LEN); packet->type = ERR; len = strlen(error); memcpy(buffer+PACKET_LEN, error, len+1); base64_encode(buffer, buffer2, PACKET_LEN + len); where = add_reply(hdr, where, TYPE_KEY, buffer2); return (where - req); }
static int eap_pwd_authenticate (void *arg, EAP_HANDLER *handler) { pwd_session_t *pwd_session; pwd_hdr *hdr; pwd_id_packet *id; EAP_PACKET *response; REQUEST *request, *fake; VALUE_PAIR *pw, **outvps, *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 == NULL) || ((eap_ds = handler->eap_ds) == NULL) || (inst == NULL)) { 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 = malloc(pwd_session->in_buf_len)) == NULL) { RDEBUG2("pwd cannot malloc %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.type = PW_EAP_PWD; eap_ds->request->type.length = sizeof(pwd_hdr); if ((eap_ds->request->type.data = malloc(sizeof(pwd_hdr))) == NULL) { radlog(L_ERR, "rlm_eap_pwd: fragment ACK, out of memory"); 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; } if ((fake->username = pairmake("User-Name", "", T_OP_EQ)) == NULL) { 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 == NULL) ? "" : fake->server); } /* * Call authorization recursively, which will * get the password. */ module_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 == NULL) ? "" : 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 = malloc(pwd_session->out_buf_len)) == NULL) { radlog(L_ERR, "rlm_eap_pwd: out of memory to send commit"); 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)) { radlog(L_ERR, "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 = malloc(pwd_session->out_buf_len)) == NULL) { radlog(L_ERR, "rlm_eap_pwd: out of memory to send confirm"); 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) */ outvps = &handler->request->reply->vps; add_reply(outvps, "MS-MPPE-Recv-Key", msk, MPPE_KEY_LEN); add_reply(outvps, "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) { free(pwd_session->in_buf); pwd_session->in_buf = NULL; } return ret; }
static void add_reply_bulklen(sub_client *c, sds cnt) { size_t len = sdslen(cnt); sds lensds = sdscatprintf(sdsempty(), "$%lu\r\n", len); add_reply(c, lensds); }
void add_reply_bulk(sub_client *c, sds cnt) { add_reply_bulklen(c, cnt); add_reply(c, cnt); add_reply(c, shared.crlf); }
static void ping_command(sub_client *c) { add_reply(c, shared.pong); }