static int recv_auth_reply(worker_st * ws, int sd, char **txt) { int ret; SecAuthReplyMsg *msg = NULL; PROTOBUF_ALLOCATOR(pa, ws); ret = recv_msg(ws, sd, SM_CMD_AUTH_REP, (void *)&msg, (unpack_func) sec_auth_reply_msg__unpack); if (ret < 0) { oclog(ws, LOG_ERR, "error receiving auth reply message"); return ret; } oclog(ws, LOG_DEBUG, "received auth reply message (value: %u)", (unsigned)msg->reply); if (txt) *txt = NULL; switch (msg->reply) { case AUTH__REP__MSG: if (txt == NULL || msg->msg == NULL) { oclog(ws, LOG_ERR, "received unexpected msg"); return ERR_AUTH_FAIL; } *txt = talloc_strdup(ws, msg->msg); if (msg->has_sid && msg->sid.len == sizeof(ws->sid)) { /* update our sid */ memcpy(ws->sid, msg->sid.data, sizeof(ws->sid)); ws->sid_set = 1; } ret = ERR_AUTH_CONTINUE; goto cleanup; case AUTH__REP__OK: if (msg->user_name == NULL) { ret = ERR_AUTH_FAIL; goto cleanup; } strlcpy(ws->username, msg->user_name, sizeof(ws->username)); if (msg->has_sid && msg->sid.len == sizeof(ws->sid)) { /* update our sid */ memcpy(ws->sid, msg->sid.data, sizeof(ws->sid)); ws->sid_set = 1; } if (msg->has_cookie == 0 || msg->cookie.len == 0 || msg->dtls_session_id.len != sizeof(ws->session_id)) { ret = ERR_AUTH_FAIL; goto cleanup; } ws->cookie = talloc_memdup(ws, msg->cookie.data, msg->cookie.len); if (ws->cookie) { ws->cookie_size = msg->cookie.len; ws->cookie_set = 1; } memcpy(ws->session_id, msg->dtls_session_id.data, msg->dtls_session_id.len); if (txt) *txt = talloc_strdup(ws, msg->msg); break; case AUTH__REP__FAILED: default: if (msg->reply != AUTH__REP__FAILED) oclog(ws, LOG_ERR, "unexpected auth reply %u", (unsigned)msg->reply); ret = ERR_AUTH_FAIL; goto cleanup; } ret = 0; cleanup: sec_auth_reply_msg__free_unpacked(msg, &pa); return ret; }
static int process_packet_from_main(void *pool, int fd, sec_mod_st * sec, cmd_request_t cmd, uint8_t * buffer, size_t buffer_size) { gnutls_datum_t data; int ret; PROTOBUF_ALLOCATOR(pa, pool); seclog(sec, LOG_DEBUG, "cmd [size=%d] %s\n", (int)buffer_size, cmd_request_to_str(cmd)); data.data = buffer; data.size = buffer_size; switch (cmd) { case CMD_SECM_LIST_COOKIES: handle_secm_list_cookies_reply(pool, fd, sec); return 0; case CMD_SECM_BAN_IP_REPLY:{ BanIpReplyMsg *msg = NULL; msg = ban_ip_reply_msg__unpack(&pa, data.size, data.data); if (msg == NULL) { seclog(sec, LOG_INFO, "error unpacking auth ban ip reply\n"); return ERR_BAD_COMMAND; } handle_sec_auth_ban_ip_reply(sec, msg); ban_ip_reply_msg__free_unpacked(msg, &pa); return 0; } case CMD_SECM_SESSION_OPEN:{ SecmSessionOpenMsg *msg; msg = secm_session_open_msg__unpack(&pa, data.size, data.data); if (msg == NULL) { seclog(sec, LOG_INFO, "error unpacking session open\n"); return ERR_BAD_COMMAND; } ret = handle_secm_session_open_cmd(sec, fd, msg); secm_session_open_msg__free_unpacked(msg, &pa); return ret; } case CMD_SECM_SESSION_CLOSE:{ SecmSessionCloseMsg *msg; msg = secm_session_close_msg__unpack(&pa, data.size, data.data); if (msg == NULL) { seclog(sec, LOG_INFO, "error unpacking session close\n"); return ERR_BAD_COMMAND; } ret = handle_secm_session_close_cmd(sec, fd, msg); secm_session_close_msg__free_unpacked(msg, &pa); return ret; } default: seclog(sec, LOG_WARNING, "unknown type 0x%.2x", cmd); return ERR_BAD_COMMAND; } return 0; }
/* auth reply from main process */ static int recv_cookie_auth_reply(worker_st * ws) { unsigned i; int ret; int socketfd = -1; AuthReplyMsg *msg = NULL; PROTOBUF_ALLOCATOR(pa, ws); ret = recv_socket_msg(ws, ws->cmd_fd, AUTH_COOKIE_REP, &socketfd, (void *)&msg, (unpack_func) auth_reply_msg__unpack); if (ret < 0) { oclog(ws, LOG_ERR, "error receiving auth reply message"); return ret; } oclog(ws, LOG_DEBUG, "received auth reply message (value: %u)", (unsigned)msg->reply); switch (msg->reply) { case AUTH__REP__OK: if (socketfd != -1) { ws->tun_fd = socketfd; if (msg->vname == NULL || msg->user_name == NULL) { ret = ERR_AUTH_FAIL; goto cleanup; } strlcpy(ws->vinfo.name, msg->vname, sizeof(ws->vinfo.name)); strlcpy(ws->username, msg->user_name, sizeof(ws->username)); if (msg->group_name != NULL) { strlcpy(ws->groupname, msg->group_name, sizeof(ws->groupname)); } else { ws->groupname[0] = 0; } memcpy(ws->session_id, msg->session_id.data, msg->session_id.len); if (msg->ipv4 != NULL) { talloc_free(ws->vinfo.ipv4); if (strcmp(msg->ipv4, "0.0.0.0") == 0) ws->vinfo.ipv4 = NULL; else ws->vinfo.ipv4 = talloc_strdup(ws, msg->ipv4); } if (msg->ipv6 != NULL) { talloc_free(ws->vinfo.ipv6); if (strcmp(msg->ipv6, "::") == 0) ws->vinfo.ipv6 = NULL; else ws->vinfo.ipv6 = talloc_strdup(ws, msg->ipv6); } if (msg->ipv4_local != NULL) { talloc_free(ws->vinfo.ipv4_local); if (strcmp(msg->ipv4_local, "0.0.0.0") == 0) ws->vinfo.ipv4_local = NULL; else ws->vinfo.ipv4_local = talloc_strdup(ws, msg->ipv4_local); } if (msg->ipv6_local != NULL) { talloc_free(ws->vinfo.ipv6_local); if (strcmp(msg->ipv6_local, "::") == 0) ws->vinfo.ipv6_local = NULL; else ws->vinfo.ipv6_local = talloc_strdup(ws, msg->ipv6_local); } /* Read any additional data */ if (msg->ipv4_netmask != NULL) { talloc_free(ws->config->network.ipv4_netmask); ws->config->network.ipv4_netmask = talloc_strdup(ws, msg->ipv4_netmask); } if (msg->ipv4_network != NULL) { talloc_free(ws->config->network.ipv4_network); ws->config->network.ipv4_network = talloc_strdup(ws, msg->ipv4_network); } if (msg->ipv6_network != NULL) { talloc_free(ws->config->network.ipv6_network); ws->config->network.ipv6_network = talloc_strdup(ws, msg->ipv6_network); } if (msg->has_ipv6_prefix) { ws->config->network.ipv6_prefix = msg->ipv6_prefix; } if (msg->has_rx_per_sec) ws->config->rx_per_sec = msg->rx_per_sec; if (msg->has_tx_per_sec) ws->config->tx_per_sec = msg->tx_per_sec; if (msg->has_net_priority) ws->config->net_priority = msg->net_priority; if (msg->has_no_udp && msg->no_udp != 0) ws->perm_config->udp_port = 0; if (msg->xml_config_file) { talloc_free(ws->config->xml_config_file); ws->config->xml_config_file = talloc_strdup(ws, msg->xml_config_file); } /* routes */ ws->routes = talloc_size(ws, msg->n_routes*sizeof(char*)); if (ws->routes != NULL) { ws->routes_size = msg->n_routes; for (i = 0; i < ws->routes_size; i++) { ws->routes[i] = talloc_strdup(ws, msg->routes[i]); /* If a default route is detected */ if (ws->routes[i] != NULL && (strcmp(ws->routes[i], "default") == 0 || strcmp(ws->routes[i], "0.0.0.0/0") == 0)) { /* disable all routes */ ws->routes_size = 0; ws->default_route = 1; break; } } } if (check_if_default_route(ws->routes, ws->routes_size)) ws->default_route = 1; ws->no_routes = talloc_size(ws, msg->n_no_routes*sizeof(char*)); if (ws->no_routes != NULL) { ws->no_routes_size = msg->n_no_routes; for (i = 0; i < ws->no_routes_size; i++) { ws->no_routes[i] = talloc_strdup(ws, msg->no_routes[i]); } } ws->dns = talloc_size(ws, msg->n_dns*sizeof(char*)); if (ws->dns != NULL) { ws->dns_size = msg->n_dns; for (i = 0; i < ws->dns_size; i++) { ws->dns[i] = talloc_strdup(ws, msg->dns[i]); } } ws->nbns = talloc_size(ws, msg->n_nbns*sizeof(char*)); if (ws->nbns != NULL) { ws->nbns_size = msg->n_nbns; for (i = 0; i < ws->nbns_size; i++) { ws->nbns[i] = talloc_strdup(ws, msg->nbns[i]); } } } else { oclog(ws, LOG_ERR, "error in received message"); ret = ERR_AUTH_FAIL; goto cleanup; } break; case AUTH__REP__FAILED: default: if (msg->reply != AUTH__REP__FAILED) oclog(ws, LOG_ERR, "unexpected auth reply %u", (unsigned)msg->reply); ret = ERR_AUTH_FAIL; goto cleanup; } ret = 0; cleanup: auth_reply_msg__free_unpacked(msg, &pa); return ret; }
static int process_worker_packet(void *pool, int cfd, pid_t pid, sec_mod_st * sec, cmd_request_t cmd, uint8_t * buffer, size_t buffer_size) { unsigned i; gnutls_datum_t data, out; int ret; SecOpMsg *op; PROTOBUF_ALLOCATOR(pa, pool); seclog(sec, LOG_DEBUG, "cmd [size=%d] %s\n", (int)buffer_size, cmd_request_to_str(cmd)); data.data = buffer; data.size = buffer_size; switch (cmd) { case CMD_SEC_SIGN: case CMD_SEC_DECRYPT: op = sec_op_msg__unpack(&pa, data.size, data.data); if (op == NULL) { seclog(sec, LOG_INFO, "error unpacking sec op\n"); return -1; } i = op->key_idx; if (op->has_key_idx == 0 || i >= sec->key_size) { seclog(sec, LOG_INFO, "received out-of-bounds key index (%d)", i); return -1; } data.data = op->data.data; data.size = op->data.len; if (cmd == CMD_SEC_DECRYPT) { ret = gnutls_privkey_decrypt_data(sec->key[i], 0, &data, &out); } else { #if GNUTLS_VERSION_NUMBER >= 0x030200 ret = gnutls_privkey_sign_hash(sec->key[i], 0, GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA, &data, &out); #else ret = gnutls_privkey_sign_raw_data(sec->key[i], 0, &data, &out); #endif } sec_op_msg__free_unpacked(op, &pa); if (ret < 0) { seclog(sec, LOG_INFO, "error in crypto operation: %s", gnutls_strerror(ret)); return -1; } ret = handle_op(pool, cfd, sec, cmd, out.data, out.size); gnutls_free(out.data); return ret; case CMD_SEC_CLI_STATS:{ CliStatsMsg *tmsg; tmsg = cli_stats_msg__unpack(&pa, data.size, data.data); if (tmsg == NULL) { seclog(sec, LOG_ERR, "error unpacking data"); return -1; } ret = handle_sec_auth_stats_cmd(sec, tmsg, pid); cli_stats_msg__free_unpacked(tmsg, &pa); return ret; } break; case CMD_SEC_AUTH_INIT:{ SecAuthInitMsg *auth_init; auth_init = sec_auth_init_msg__unpack(&pa, data.size, data.data); if (auth_init == NULL) { seclog(sec, LOG_INFO, "error unpacking auth init\n"); return -1; } ret = handle_sec_auth_init(cfd, sec, auth_init, pid); sec_auth_init_msg__free_unpacked(auth_init, &pa); return ret; } case CMD_SEC_AUTH_CONT:{ SecAuthContMsg *auth_cont; auth_cont = sec_auth_cont_msg__unpack(&pa, data.size, data.data); if (auth_cont == NULL) { seclog(sec, LOG_INFO, "error unpacking auth cont\n"); return -1; } ret = handle_sec_auth_cont(cfd, sec, auth_cont); sec_auth_cont_msg__free_unpacked(auth_cont, &pa); return ret; } case RESUME_STORE_REQ:{ SessionResumeStoreReqMsg *smsg; smsg = session_resume_store_req_msg__unpack(&pa, buffer_size, buffer); if (smsg == NULL) { seclog(sec, LOG_ERR, "error unpacking data"); return ERR_BAD_COMMAND; } ret = handle_resume_store_req(sec, smsg); /* zeroize the data */ safe_memset(buffer, 0, buffer_size); safe_memset(smsg->session_data.data, 0, smsg->session_data.len); session_resume_store_req_msg__free_unpacked(smsg, &pa); if (ret < 0) { seclog(sec, LOG_DEBUG, "could not store resumption data"); } } break; case RESUME_DELETE_REQ:{ SessionResumeFetchMsg *fmsg; fmsg = session_resume_fetch_msg__unpack(&pa, buffer_size, buffer); if (fmsg == NULL) { seclog(sec, LOG_ERR, "error unpacking data"); return ERR_BAD_COMMAND; } ret = handle_resume_delete_req(sec, fmsg); session_resume_fetch_msg__free_unpacked(fmsg, &pa); if (ret < 0) { seclog(sec, LOG_DEBUG, "could not delete resumption data."); } } break; case RESUME_FETCH_REQ:{ SessionResumeReplyMsg msg = SESSION_RESUME_REPLY_MSG__INIT; SessionResumeFetchMsg *fmsg; /* FIXME: rate limit that */ fmsg = session_resume_fetch_msg__unpack(&pa, buffer_size, buffer); if (fmsg == NULL) { seclog(sec, LOG_ERR, "error unpacking data"); return ERR_BAD_COMMAND; } ret = handle_resume_fetch_req(sec, fmsg, &msg); session_resume_fetch_msg__free_unpacked(fmsg, &pa); if (ret < 0) { msg.reply = SESSION_RESUME_REPLY_MSG__RESUME__REP__FAILED; seclog(sec, LOG_DEBUG, "could not fetch resumption data."); } else { msg.reply = SESSION_RESUME_REPLY_MSG__RESUME__REP__OK; } ret = send_msg(pool, cfd, RESUME_FETCH_REP, &msg, (pack_size_func) session_resume_reply_msg__get_packed_size, (pack_func) session_resume_reply_msg__pack); if (ret < 0) { seclog(sec, LOG_ERR, "could not send reply cmd %d.", (unsigned)cmd); return ERR_BAD_COMMAND; } } break; default: seclog(sec, LOG_WARNING, "unknown type 0x%.2x", cmd); return -1; } return 0; }