int Ctgdb::Process_console_command(tgdb_request_ptr request) { struct ibuf *command; if (!request) return -1; if (!Can_issue_command()) return -1; if (request->header != TGDB_REQUEST_CONSOLE_COMMAND) return -1; command = ibuf_init (); ibuf_add (command, request->choice.console_command.command); ibuf_addchar (command, '\n'); if (Send(ibuf_get (command), TGDB_COMMAND_CONSOLE) == -1) { Logger_write_pos( __FILE__, __LINE__, "tgdb_send failed"); return -1; } ibuf_free (command); command = NULL; return 0; }
struct ibuf *ibuf_dup(struct ibuf *s) { struct ibuf *ns = ibuf_init(); ibuf_add(ns, ibuf_get(s)); return ns; }
static int test_add(ibuf s) { /* Add the strings "hello" and " world" to the ibuf */ ibuf_add(s, "hello"); ibuf_add(s, " world"); /* Make sure that's what got added */ if (strcmp(ibuf_get(s), "hello world") != 0) { debug("test_add: Mismatch, expected \"hello world\", got: %s\n", ibuf_get(s)); return 1; } debug("test_add: Succeeded.\n"); return 0; }
struct iked_message * ikev2_msg_copy(struct iked *env, struct iked_message *msg) { struct iked_message *m = NULL; struct ibuf *buf; size_t len; void *ptr; if (ibuf_size(msg->msg_data) < msg->msg_offset) return (NULL); len = ibuf_size(msg->msg_data) - msg->msg_offset; if ((ptr = ibuf_seek(msg->msg_data, msg->msg_offset, len)) == NULL || (m = malloc(sizeof(*m))) == NULL || (buf = ikev2_msg_init(env, m, &msg->msg_peer, msg->msg_peerlen, &msg->msg_local, msg->msg_locallen, msg->msg_response)) == NULL || ibuf_add(buf, ptr, len)) return (NULL); m->msg_fd = msg->msg_fd; m->msg_msgid = msg->msg_msgid; m->msg_offset = msg->msg_offset; m->msg_sa = msg->msg_sa; return (m); }
int imsg_add(struct ibuf *msg, const void *data, u_int16_t datalen) { if (datalen) if (ibuf_add(msg, data, datalen) == -1) { ibuf_free(msg); return (-1); } return (datalen); }
int eap_challenge_request(struct iked *env, struct iked_sa *sa, struct eap_header *hdr) { struct eap_message *eap; struct eap_mschap_challenge *ms; const char *name; int ret = -1; struct ibuf *e; if ((e = ibuf_static()) == NULL) return (-1); if ((eap = ibuf_advance(e, sizeof(*eap))) == NULL) goto done; eap->eap_code = EAP_CODE_REQUEST; eap->eap_id = hdr->eap_id + 1; eap->eap_type = sa->sa_policy->pol_auth.auth_eap; switch (sa->sa_policy->pol_auth.auth_eap) { case EAP_TYPE_MSCHAP_V2: name = IKED_USER; /* XXX should be user-configurable */ eap->eap_length = htobe16(sizeof(*eap) + sizeof(*ms) + strlen(name)); if ((ms = ibuf_advance(e, sizeof(*ms))) == NULL) return (-1); ms->msc_opcode = EAP_MSOPCODE_CHALLENGE; ms->msc_id = eap->eap_id; ms->msc_length = htobe16(sizeof(*ms) + strlen(name)); ms->msc_valuesize = sizeof(ms->msc_challenge); arc4random_buf(ms->msc_challenge, sizeof(ms->msc_challenge)); if (ibuf_add(e, name, strlen(name)) == -1) goto done; /* Store the EAP challenge value */ sa->sa_eap.id_type = eap->eap_type; if ((sa->sa_eap.id_buf = ibuf_new(ms->msc_challenge, sizeof(ms->msc_challenge))) == NULL) goto done; break; default: log_debug("%s: unsupported EAP type %s", __func__, print_map(eap->eap_type, eap_type_map)); goto done; } ret = ikev2_send_ike_e(env, sa, e, IKEV2_PAYLOAD_EAP, IKEV2_EXCHANGE_IKE_AUTH, 1); done: ibuf_release(e); return (ret); }
static int test_trim(ibuf s) { /* Test #1: Empty string. */ ibuf_clear(s); ibuf_trim(s); if (strcmp(ibuf_get(s), "") != 0) { debug("test_trim: 1: expected empty string, got: %s\n", ibuf_get(s)); return 1; } /* Test #2: Single space. */ ibuf_clear(s); ibuf_addchar(s, ' '); ibuf_trim(s); if (strcmp(ibuf_get(s), "") != 0) { debug("test_trim: 2: expected empty string, got: %s\n", ibuf_get(s)); return 2; } /* Test #3: "hello world" (no leading or trailing spaces) */ ibuf_clear(s); ibuf_add(s, "hello world"); ibuf_trim(s); if (strcmp(ibuf_get(s), "hello world") != 0) { debug("test_trim: 3: expected \"hello world\", got: %s\n", ibuf_get(s)); return 3; } /* Test #4: " hello world \t" (leading and trailing spaces) */ ibuf_clear(s); ibuf_add(s, " hello world \t"); ibuf_trim(s); if (strcmp(ibuf_get(s), "hello world") != 0) { debug("test_trim: 4: expected \"hello world\", got: %s\n", ibuf_get(s)); return 3; } debug("test_trim: Succeeded.\n"); return 0; }
void tcp_read_buf(int s, short event, void *arg) { ssize_t br; char rbuf[SMALL_READ_BUF_SIZE]; struct ctl_tcp_event *cte = arg; if (event == EV_TIMEOUT) { cte->host->up = HOST_DOWN; ibuf_free(cte->buf); close(s); hce_notify_done(cte->host, HCE_TCP_READ_TIMEOUT); return; } bzero(rbuf, sizeof(rbuf)); br = read(s, rbuf, sizeof(rbuf) - 1); switch (br) { case -1: if (errno == EAGAIN || errno == EINTR) goto retry; cte->host->up = HOST_DOWN; ibuf_free(cte->buf); close(cte->s); hce_notify_done(cte->host, HCE_TCP_READ_FAIL); return; case 0: cte->host->up = HOST_DOWN; (void)cte->validate_close(cte); close(cte->s); ibuf_free(cte->buf); hce_notify_done(cte->host, cte->host->he); return; default: if (ibuf_add(cte->buf, rbuf, br) == -1) fatal("tcp_read_buf: buf_add error"); if (cte->validate_read != NULL) { if (cte->validate_read(cte) != 0) goto retry; close(cte->s); ibuf_free(cte->buf); hce_notify_done(cte->host, cte->host->he); return; } break; /* retry */ } retry: event_again(&cte->ev, s, EV_TIMEOUT|EV_READ, tcp_read_buf, &cte->tv_start, &cte->table->conf.timeout, cte); }
void gen_address_list_tlv(struct ibuf *buf, struct iface *iface, u_int16_t size) { struct address_list_tlv alt; struct iface *niface; /* We want just the size of the value */ size -= TLV_HDR_LEN; bzero(&alt, sizeof(alt)); alt.type = TLV_TYPE_ADDRLIST; alt.length = htons(size); /* XXX: just ipv4 for now */ alt.family = htons(ADDR_IPV4); ibuf_add(buf, &alt, sizeof(alt)); if (iface == NULL) LIST_FOREACH(niface, &leconf->iface_list, entry) ibuf_add(buf, &niface->addr, sizeof(niface->addr)); else ibuf_add(buf, &iface->addr, sizeof(iface->addr)); }
int highlight_node(const char *filename, struct buffer *buf) { int ret; int length = 0; int lasttype = -1; struct ibuf *ibuf = ibuf_init(); struct tokenizer *t = tokenizer_init(); if (tokenizer_set_file(t, filename, buf->language) == -1) { if_print_message("%s:%d tokenizer_set_file error", __FILE__, __LINE__); return -1; } while ((ret = tokenizer_get_token(t)) > 0) { enum tokenizer_type e = tokenizer_get_packet_type(t); /*if_print_message ( "TOKEN(%d:%s)\n", e, tokenizer_get_printable_enum ( e ) ); */ if (e == TOKENIZER_NEWLINE) { sbpush(buf->tlines, strdup(ibuf_get(ibuf))); if (length > buf->max_width) buf->max_width = length; length = 0; lasttype = -1; ibuf_clear(ibuf); } else { const char *tok_data = tokenizer_get_data(t); enum hl_group_kind hlg = hlg_from_tokenizer_type(e, tok_data); if (hlg == HLG_LAST) { logger_write_pos(logger, __FILE__, __LINE__, "Bad hlg_type for '%s', e==%d\n", tok_data, e); hlg = HLG_TEXT; } /* Set the highlight group type */ add_type(ibuf, &lasttype, hlg); /* Add the text and bump our length */ length += ibuf_add(ibuf, tok_data); } } ibuf_free(ibuf); tokenizer_destroy(t); return 0; }
int gen_hello_prms_tlv(struct iface *iface, struct ibuf *buf, u_int16_t size) { struct hello_prms_tlv parms; /* We want just the size of the value */ size -= TLV_HDR_LEN; bzero(&parms, sizeof(parms)); parms.type = htons(TLV_TYPE_COMMONHELLO); parms.length = htons(size); /* XXX */ parms.holdtime = htons(iface->holdtime); parms.flags = 0; return (ibuf_add(buf, &parms, sizeof(parms))); }
int gen_status_tlv(struct ibuf *buf, u_int32_t status, u_int32_t msgid, u_int32_t type) { struct status_tlv st; bzero(&st, sizeof(st)); st.type = htons(TLV_TYPE_STATUS); st.length = htons(STATUS_TLV_LEN); st.status_code = htonl(status); st.msg_id = msgid; st.msg_type = type; return (ibuf_add(buf, &st, STATUS_SIZE)); }
int gen_status_tlv(struct ibuf *buf, uint32_t status_code, uint32_t msg_id, uint16_t msg_type) { struct status_tlv st; memset(&st, 0, sizeof(st)); st.type = htons(TLV_TYPE_STATUS); st.length = htons(STATUS_TLV_LEN); st.status_code = htonl(status_code); /* * For convenience, msg_id and msg_type are already in network * byte order. */ st.msg_id = msg_id; st.msg_type = msg_type; return (ibuf_add(buf, &st, STATUS_SIZE)); }
int gen_init_prms_tlv(struct ibuf *buf, struct nbr *nbr, u_int16_t size) { struct sess_prms_tlv parms; /* We want just the size of the value */ size -= TLV_HDR_LEN; bzero(&parms, sizeof(parms)); parms.type = htons(TLV_TYPE_COMMONSESSION); parms.length = htons(size); parms.proto_version = htons(LDP_VERSION); parms.keepalive_time = htons(leconf->keepalive); parms.reserved = 0; parms.pvlim = 0; parms.max_pdu_len = 0; parms.lsr_id = nbr->id.s_addr; parms.lspace_id = 0; return (ibuf_add(buf, &parms, SESS_PRMS_SIZE)); }
static int test_dup(ibuf s) { ibuf t; /* Test duplicating a string. */ ibuf_add(s, "test string 1"); t = ibuf_dup(s); if (t == NULL) { debug("test_dup: ibuf_dup (attempt #1) returned NULL\n"); return 1; } if (strcmp(ibuf_get(s), ibuf_get(t)) != 0) { debug("test_dup: Strings mismatched: \"%s\" != \"%s\"\n", ibuf_get(s), ibuf_get(t)); return 1; } ibuf_free(t); /* Corner case: duplicate an empty string */ ibuf_clear(s); t = ibuf_dup(s); if (t == NULL) { debug("test_dup: ibuf_dup (attempt #2) returned NULL\n"); return 1; } if (strcmp(ibuf_get(t), "") != 0) { debug("test_dup: Expected empty string, got: %s\n", ibuf_get(t)); return 1; } ibuf_free(t); debug("test_dup: Succeeded.\n"); return 0; }
int Ctgdb::Send(char *command, enum tgdb_command_choice command_choice, ITarget* target) { struct tgdb_command *tc; struct ibuf *temp_command = ibuf_init (); int length = strlen (command); /* Add a newline to the end of the command if it doesn't exist */ ibuf_add (temp_command, command); if (command[length - 1] != '\n') ibuf_addchar (temp_command, '\n'); /* Create the client command */ tc = tgdb_command_create (ibuf_get (temp_command), command_choice, NULL); tc->ITarget = (void*) target; ibuf_free (temp_command); temp_command = NULL; if (Run_or_queue_command(tc) == -1) { Logger_write_pos( __FILE__, __LINE__, "tgdb_run_or_queue_command failed"); return -1; } if (tgdb_client_tgdb_ran_command(tcc) == -1) { Logger_write_pos( __FILE__, __LINE__, "tgdb_client_tgdb_ran_command failed"); return -1; } Process_client_commands(); return 0; }
/* database description packet handling */ int send_db_description(struct nbr *nbr) { struct in6_addr dst; struct db_dscrp_hdr dd_hdr; struct lsa_entry *le, *nle; struct ibuf *buf; int ret = 0; u_int8_t bits = 0; if ((buf = ibuf_open(nbr->iface->mtu - sizeof(struct ip))) == NULL) fatal("send_db_description"); /* OSPF header */ if (gen_ospf_hdr(buf, nbr->iface, PACKET_TYPE_DD)) goto fail; /* reserve space for database description header */ if (ibuf_reserve(buf, sizeof(dd_hdr)) == NULL) goto fail; switch (nbr->state) { case NBR_STA_DOWN: case NBR_STA_ATTEMPT: case NBR_STA_INIT: case NBR_STA_2_WAY: case NBR_STA_SNAP: log_debug("send_db_description: cannot send packet in state %s," " neighbor ID %s", nbr_state_name(nbr->state), inet_ntoa(nbr->id)); ret = -1; goto done; case NBR_STA_XSTRT: bits |= OSPF_DBD_MS | OSPF_DBD_M | OSPF_DBD_I; nbr->dd_more = 1; break; case NBR_STA_XCHNG: if (nbr->dd_master) bits |= OSPF_DBD_MS; else bits &= ~OSPF_DBD_MS; if (TAILQ_EMPTY(&nbr->db_sum_list)) { bits &= ~OSPF_DBD_M; nbr->dd_more = 0; } else { bits |= OSPF_DBD_M; nbr->dd_more = 1; } bits &= ~OSPF_DBD_I; /* build LSA list */ for (le = TAILQ_FIRST(&nbr->db_sum_list); le != NULL && buf->wpos + sizeof(struct lsa_hdr) < buf->max; le = nle) { nbr->dd_end = nle = TAILQ_NEXT(le, entry); if (ibuf_add(buf, le->le_lsa, sizeof(struct lsa_hdr))) goto fail; } break; case NBR_STA_LOAD: case NBR_STA_FULL: if (nbr->dd_master) bits |= OSPF_DBD_MS; else bits &= ~OSPF_DBD_MS; bits &= ~OSPF_DBD_M; bits &= ~OSPF_DBD_I; nbr->dd_more = 0; break; default: fatalx("send_db_description: unknown neighbor state"); } bzero(&dd_hdr, sizeof(dd_hdr)); switch (nbr->iface->type) { case IF_TYPE_POINTOPOINT: inet_pton(AF_INET6, AllSPFRouters, &dst); dd_hdr.iface_mtu = htons(nbr->iface->mtu); break; case IF_TYPE_BROADCAST: dst = nbr->addr; dd_hdr.iface_mtu = htons(nbr->iface->mtu); break; case IF_TYPE_NBMA: case IF_TYPE_POINTOMULTIPOINT: /* XXX not supported */ break; case IF_TYPE_VIRTUALLINK: dst = nbr->iface->dst; dd_hdr.iface_mtu = 0; break; default: fatalx("send_db_description: unknown interface type"); } dd_hdr.opts = htonl(area_ospf_options(area_find(oeconf, nbr->iface->area_id))); dd_hdr.bits = bits; dd_hdr.dd_seq_num = htonl(nbr->dd_seq_num); memcpy(ibuf_seek(buf, sizeof(struct ospf_hdr), sizeof(dd_hdr)), &dd_hdr, sizeof(dd_hdr)); /* calculate checksum */ if (upd_ospf_hdr(buf, nbr->iface)) goto fail; /* transmit packet */ ret = send_packet(nbr->iface, buf->buf, buf->wpos, &dst); done: ibuf_free(buf); return (ret); fail: log_warn("send_db_description"); ibuf_free(buf); return (-1); }
void ssl_read(int s, short event, void *arg) { char rbuf[SMALL_READ_BUF_SIZE]; struct ctl_tcp_event *cte = arg; int retry_flag = EV_READ; int tls_err = 0; int ret; if (event == EV_TIMEOUT) { cte->host->up = HOST_DOWN; ssl_cleanup(cte); hce_notify_done(cte->host, HCE_TLS_READ_TIMEOUT); return; } bzero(rbuf, sizeof(rbuf)); ret = SSL_read(cte->ssl, rbuf, sizeof(rbuf)); if (ret <= 0) { tls_err = SSL_get_error(cte->ssl, ret); switch (tls_err) { case SSL_ERROR_WANT_READ: retry_flag = EV_READ; goto retry; case SSL_ERROR_WANT_WRITE: retry_flag = EV_WRITE; goto retry; case SSL_ERROR_ZERO_RETURN: /* FALLTHROUGH */ case SSL_ERROR_SYSCALL: if (ret == 0) { cte->host->up = HOST_DOWN; (void)cte->validate_close(cte); ssl_cleanup(cte); hce_notify_done(cte->host, cte->host->he); return; } /* FALLTHROUGH */ default: cte->host->up = HOST_DOWN; ssl_error(cte->host->conf.name, "cannot read"); ssl_cleanup(cte); hce_notify_done(cte->host, HCE_TLS_READ_ERROR); break; } return; } if (ibuf_add(cte->buf, rbuf, ret) == -1) fatal("ssl_read: buf_add error"); if (cte->validate_read != NULL) { if (cte->validate_read(cte) != 0) goto retry; ssl_cleanup(cte); hce_notify_done(cte->host, cte->host->he); return; } retry: event_again(&cte->ev, s, EV_TIMEOUT|retry_flag, ssl_read, &cte->tv_start, &cte->table->conf.timeout, cte); return; }
struct ibuf * ikev2_msg_encrypt(struct iked *env, struct iked_sa *sa, struct ibuf *src) { size_t len, encrlen, integrlen, blocklen, outlen; uint8_t *buf, pad = 0, *ptr; struct ibuf *encr, *dst = NULL, *out = NULL; buf = ibuf_data(src); len = ibuf_size(src); log_debug("%s: decrypted length %zu", __func__, len); print_hex(buf, 0, len); if (sa == NULL || sa->sa_encr == NULL || sa->sa_integr == NULL) { log_debug("%s: invalid SA", __func__); goto done; } if (sa->sa_hdr.sh_initiator) encr = sa->sa_key_iencr; else encr = sa->sa_key_rencr; blocklen = cipher_length(sa->sa_encr); integrlen = hash_length(sa->sa_integr); encrlen = roundup(len + sizeof(pad), blocklen); pad = encrlen - (len + sizeof(pad)); /* * Pad the payload and encrypt it */ if (pad) { if ((ptr = ibuf_advance(src, pad)) == NULL) goto done; arc4random_buf(ptr, pad); } if (ibuf_add(src, &pad, sizeof(pad)) != 0) goto done; log_debug("%s: padded length %zu", __func__, ibuf_size(src)); print_hex(ibuf_data(src), 0, ibuf_size(src)); cipher_setkey(sa->sa_encr, encr->buf, ibuf_length(encr)); cipher_setiv(sa->sa_encr, NULL, 0); cipher_init_encrypt(sa->sa_encr); if ((dst = ibuf_dup(sa->sa_encr->encr_iv)) == NULL) goto done; if ((out = ibuf_new(NULL, cipher_outlength(sa->sa_encr, encrlen))) == NULL) goto done; outlen = ibuf_size(out); cipher_update(sa->sa_encr, ibuf_data(src), encrlen, ibuf_data(out), &outlen); if (outlen && ibuf_add(dst, ibuf_data(out), outlen) != 0) goto done; if ((ptr = ibuf_advance(dst, integrlen)) == NULL) goto done; explicit_bzero(ptr, integrlen); log_debug("%s: length %zu, padding %d, output length %zu", __func__, len + sizeof(pad), pad, ibuf_size(dst)); print_hex(ibuf_data(dst), 0, ibuf_size(dst)); ibuf_release(src); ibuf_release(out); return (dst); done: ibuf_release(src); ibuf_release(out); ibuf_release(dst); return (NULL); }
static int highlight_node ( struct list_node *node ) { struct tokenizer *t = tokenizer_init (); int ret; struct ibuf *ibuf = ibuf_init (); ibuf_addchar ( ibuf, HL_CHAR ); ibuf_addchar ( ibuf, HLG_TEXT ); /* Initialize */ node->buf.length = 0; node->buf.tlines = NULL; node->buf.max_width = 0; if ( tokenizer_set_file ( t, node->path, node->language ) == -1 ) { if_print_message ("%s:%d tokenizer_set_file error", __FILE__, __LINE__); return -1; } while ( ( ret = tokenizer_get_token ( t ) ) > 0 ) { enum tokenizer_type e = tokenizer_get_packet_type ( t ); /*if_print_message ( "TOKEN(%d:%s)\n", e, tokenizer_get_printable_enum ( e ) );*/ switch ( e ) { case TOKENIZER_KEYWORD: ibuf_addchar ( ibuf, HL_CHAR ); ibuf_addchar ( ibuf, HLG_KEYWORD ); ibuf_add ( ibuf, tokenizer_get_data ( t ) ); ibuf_addchar ( ibuf, HL_CHAR ); ibuf_addchar ( ibuf, HLG_TEXT ); break; case TOKENIZER_TYPE: ibuf_addchar ( ibuf, HL_CHAR ); ibuf_addchar ( ibuf, HLG_TYPE ); ibuf_add ( ibuf, tokenizer_get_data ( t ) ); ibuf_addchar ( ibuf, HL_CHAR ); ibuf_addchar ( ibuf, HLG_TEXT ); break; case TOKENIZER_LITERAL: ibuf_addchar ( ibuf, HL_CHAR ); ibuf_addchar ( ibuf, HLG_LITERAL ); ibuf_add ( ibuf, tokenizer_get_data ( t ) ); ibuf_addchar ( ibuf, HL_CHAR ); ibuf_addchar ( ibuf, HLG_TEXT ); break; case TOKENIZER_NUMBER: ibuf_add ( ibuf, tokenizer_get_data ( t ) ); break; case TOKENIZER_COMMENT: ibuf_addchar ( ibuf, HL_CHAR ); ibuf_addchar ( ibuf, HLG_COMMENT ); ibuf_add ( ibuf, tokenizer_get_data ( t ) ); ibuf_addchar ( ibuf, HL_CHAR ); ibuf_addchar ( ibuf, HLG_TEXT ); break; case TOKENIZER_DIRECTIVE: ibuf_addchar ( ibuf, HL_CHAR ); ibuf_addchar ( ibuf, HLG_DIRECTIVE ); ibuf_add ( ibuf, tokenizer_get_data ( t ) ); ibuf_addchar ( ibuf, HL_CHAR ); ibuf_addchar ( ibuf, HLG_TEXT ); break; case TOKENIZER_TEXT: ibuf_add ( ibuf, tokenizer_get_data ( t ) ); break; case TOKENIZER_NEWLINE: node->buf.length++; node->buf.tlines = realloc ( node->buf.tlines, sizeof ( char *) * node->buf.length ); node->buf.tlines[node->buf.length-1] = strdup ( ibuf_get ( ibuf ) ); if ( ibuf_length ( ibuf ) > node->buf.max_width ) node->buf.max_width = ibuf_length ( ibuf ); ibuf_clear ( ibuf ); ibuf_addchar ( ibuf, HL_CHAR ); ibuf_addchar ( ibuf, HLG_TEXT ); break; case TOKENIZER_ERROR: ibuf_add ( ibuf, tokenizer_get_data ( t ) ); break; default: return -1; break; } } return 0; }
int ca_reload(struct iked *env) { struct ca_store *store = env->sc_priv; uint8_t md[EVP_MAX_MD_SIZE]; char file[PATH_MAX]; struct iovec iov[2]; struct dirent *entry; STACK_OF(X509_OBJECT) *h; X509_OBJECT *xo; X509 *x509; DIR *dir; int i, len, iovcnt = 0; /* * Load CAs */ if ((dir = opendir(IKED_CA_DIR)) == NULL) return (-1); while ((entry = readdir(dir)) != NULL) { if ((entry->d_type != DT_REG) && (entry->d_type != DT_LNK)) continue; if (snprintf(file, sizeof(file), "%s%s", IKED_CA_DIR, entry->d_name) == -1) continue; if (!X509_load_cert_file(store->ca_calookup, file, X509_FILETYPE_PEM)) { log_warn("%s: failed to load ca file %s", __func__, entry->d_name); ca_sslerror(__func__); continue; } log_debug("%s: loaded ca file %s", __func__, entry->d_name); } closedir(dir); /* * Load CRLs for the CAs */ if ((dir = opendir(IKED_CRL_DIR)) == NULL) return (-1); while ((entry = readdir(dir)) != NULL) { if ((entry->d_type != DT_REG) && (entry->d_type != DT_LNK)) continue; if (snprintf(file, sizeof(file), "%s%s", IKED_CRL_DIR, entry->d_name) == -1) continue; if (!X509_load_crl_file(store->ca_calookup, file, X509_FILETYPE_PEM)) { log_warn("%s: failed to load crl file %s", __func__, entry->d_name); ca_sslerror(__func__); continue; } /* Only enable CRL checks if we actually loaded a CRL */ X509_STORE_set_flags(store->ca_cas, X509_V_FLAG_CRL_CHECK); log_debug("%s: loaded crl file %s", __func__, entry->d_name); } closedir(dir); /* * Save CAs signatures for the IKEv2 CERTREQ */ ibuf_release(env->sc_certreq); if ((env->sc_certreq = ibuf_new(NULL, 0)) == NULL) return (-1); h = store->ca_cas->objs; for (i = 0; i < sk_X509_OBJECT_num(h); i++) { xo = sk_X509_OBJECT_value(h, i); if (xo->type != X509_LU_X509) continue; x509 = xo->data.x509; len = sizeof(md); ca_subjectpubkey_digest(x509, md, &len); log_debug("%s: %s", __func__, x509->name); if (ibuf_add(env->sc_certreq, md, len) != 0) { ibuf_release(env->sc_certreq); return (-1); } } if (ibuf_length(env->sc_certreq)) { env->sc_certreqtype = IKEV2_CERT_X509_CERT; iov[0].iov_base = &env->sc_certreqtype; iov[0].iov_len = sizeof(env->sc_certreqtype); iovcnt++; iov[1].iov_base = ibuf_data(env->sc_certreq); iov[1].iov_len = ibuf_length(env->sc_certreq); iovcnt++; log_debug("%s: loaded %zu ca certificate%s", __func__, ibuf_length(env->sc_certreq) / SHA_DIGEST_LENGTH, ibuf_length(env->sc_certreq) == SHA_DIGEST_LENGTH ? "" : "s"); (void)proc_composev(&env->sc_ps, PROC_IKEV2, IMSG_CERTREQ, iov, iovcnt); } /* * Load certificates */ if ((dir = opendir(IKED_CERT_DIR)) == NULL) return (-1); while ((entry = readdir(dir)) != NULL) { if ((entry->d_type != DT_REG) && (entry->d_type != DT_LNK)) continue; if (snprintf(file, sizeof(file), "%s%s", IKED_CERT_DIR, entry->d_name) == -1) continue; if (!X509_load_cert_file(store->ca_certlookup, file, X509_FILETYPE_PEM)) { log_warn("%s: failed to load cert file %s", __func__, entry->d_name); ca_sslerror(__func__); continue; } log_debug("%s: loaded cert file %s", __func__, entry->d_name); } closedir(dir); h = store->ca_certs->objs; for (i = 0; i < sk_X509_OBJECT_num(h); i++) { xo = sk_X509_OBJECT_value(h, i); if (xo->type != X509_LU_X509) continue; x509 = xo->data.x509; (void)ca_validate_cert(env, NULL, x509, 0); } if (!env->sc_certreqtype) env->sc_certreqtype = store->ca_pubkey.id_type; log_debug("%s: local cert type %s", __func__, print_map(env->sc_certreqtype, ikev2_cert_map)); iov[0].iov_base = &env->sc_certreqtype; iov[0].iov_len = sizeof(env->sc_certreqtype); if (iovcnt == 0) iovcnt++; (void)proc_composev(&env->sc_ps, PROC_IKEV2, IMSG_CERTREQ, iov, iovcnt); return (0); }
int eap_mschap(struct iked *env, struct iked_sa *sa, struct eap_message *eap) { struct iked_user *usr; struct eap_message *resp; struct eap_mschap_response *msr; struct eap_mschap_peer *msp; struct eap_mschap *ms; struct eap_mschap_success *mss; u_int8_t *ptr, *pass; size_t len, passlen; char *name, *msg; u_int8_t ntresponse[EAP_MSCHAP_NTRESPONSE_SZ]; u_int8_t successmsg[EAP_MSCHAP_SUCCESS_SZ]; struct ibuf *eapmsg = NULL; int ret = -1; if (!sa_stateok(sa, IKEV2_STATE_EAP)) { log_debug("%s: unexpected EAP", __func__); return (0); /* ignore */ } if (sa->sa_hdr.sh_initiator) { log_debug("%s: initiator EAP not supported", __func__); return (-1); } /* Only MSCHAP-V2 */ if (eap->eap_type != EAP_TYPE_MSCHAP_V2) { log_debug("%s: unsupported type EAP-%s", __func__, print_map(eap->eap_type, eap_type_map)); return (-1); } if (betoh16(eap->eap_length) < (sizeof(*eap) + sizeof(*ms))) { log_debug("%s: short message", __func__); return (-1); } ms = (struct eap_mschap *)(eap + 1); ptr = (u_int8_t *)(eap + 1); switch (ms->ms_opcode) { case EAP_MSOPCODE_RESPONSE: msr = (struct eap_mschap_response *)ms; if (betoh16(eap->eap_length) < (sizeof(*eap) + sizeof(*msr))) { log_debug("%s: short response", __func__); return (-1); } ptr += sizeof(*msr); len = betoh16(eap->eap_length) - sizeof(*eap) - sizeof(*msr); if (len == 0 && sa->sa_eapid != NULL) name = strdup(sa->sa_eapid); else name = get_string(ptr, len); if (name == NULL) { log_debug("%s: invalid response name", __func__); return (-1); } if ((usr = user_lookup(env, name)) == NULL) { log_debug("%s: unknown user '%s'", __func__, name); free(name); return (-1); } free(name); if ((pass = string2unicode(usr->usr_pass, &passlen)) == NULL) return (-1); msp = &msr->msr_response.resp_peer; mschap_nt_response(ibuf_data(sa->sa_eap.id_buf), msp->msp_challenge, usr->usr_name, strlen(usr->usr_name), pass, passlen, ntresponse); if (memcmp(ntresponse, msp->msp_ntresponse, sizeof(ntresponse)) != 0) { log_debug("%s: '%s' authentication failed", __func__, usr->usr_name); free(pass); /* XXX should we send an EAP failure packet? */ return (-1); } bzero(&successmsg, sizeof(successmsg)); mschap_auth_response(pass, passlen, ntresponse, ibuf_data(sa->sa_eap.id_buf), msp->msp_challenge, usr->usr_name, strlen(usr->usr_name), successmsg); if ((sa->sa_eapmsk = ibuf_new(NULL, MSCHAP_MSK_SZ)) == NULL) { log_debug("%s: failed to get MSK", __func__); free(pass); return (-1); } mschap_msk(pass, passlen, ntresponse, ibuf_data(sa->sa_eapmsk)); free(pass); log_info("%s: '%s' authenticated", __func__, usr->usr_name); if ((eapmsg = ibuf_static()) == NULL) return (-1); msg = " M=Welcome"; if ((resp = ibuf_advance(eapmsg, sizeof(*resp))) == NULL) goto done; resp->eap_code = EAP_CODE_REQUEST; resp->eap_id = eap->eap_id + 1; resp->eap_length = htobe16(sizeof(*resp) + sizeof(*mss) + sizeof(successmsg) + strlen(msg)); resp->eap_type = EAP_TYPE_MSCHAP_V2; if ((mss = ibuf_advance(eapmsg, sizeof(*mss))) == NULL) goto done; mss->mss_opcode = EAP_MSOPCODE_SUCCESS; mss->mss_id = msr->msr_id; mss->mss_length = htobe16(sizeof(*mss) + sizeof(successmsg) + strlen(msg)); if (ibuf_add(eapmsg, successmsg, sizeof(successmsg)) != 0) goto done; if (ibuf_add(eapmsg, msg, strlen(msg)) != 0) goto done; break; case EAP_MSOPCODE_SUCCESS: if ((eapmsg = ibuf_static()) == NULL) return (-1); if ((resp = ibuf_advance(eapmsg, sizeof(*resp))) == NULL) goto done; resp->eap_code = EAP_CODE_RESPONSE; resp->eap_id = eap->eap_id; resp->eap_length = htobe16(sizeof(*resp) + sizeof(*ms)); resp->eap_type = EAP_TYPE_MSCHAP_V2; if ((ms = ibuf_advance(eapmsg, sizeof(*ms))) == NULL) goto done; ms->ms_opcode = EAP_MSOPCODE_SUCCESS; break; case EAP_MSOPCODE_FAILURE: case EAP_MSOPCODE_CHANGE_PASSWORD: case EAP_MSOPCODE_CHALLENGE: default: log_debug("%s: EAP-%s unsupported " "responder operation %s", __func__, print_map(eap->eap_type, eap_type_map), print_map(ms->ms_opcode, eap_msopcode_map)); return (-1); } if (eapmsg != NULL) ret = ikev2_send_ike_e(env, sa, eapmsg, IKEV2_PAYLOAD_EAP, IKEV2_EXCHANGE_IKE_AUTH, 1); if (ret == 0) sa_state(env, sa, IKEV2_STATE_AUTH_SUCCESS); done: ibuf_release(eapmsg); return (ret); }
int ikev2_pld_delete(struct iked *env, struct ikev2_payload *pld, struct iked_message *msg, off_t offset) { struct iked_childsa **peersas = NULL; struct iked_sa *sa = msg->msg_sa; struct ikev2_delete *del, *localdel; struct ibuf *resp = NULL; u_int64_t *localspi = NULL; u_int64_t spi64, spi = 0; u_int32_t spi32; u_int8_t *buf, *msgbuf = ibuf_data(msg->msg_data); size_t found = 0, failed = 0; int cnt, i, len, sz, ret = -1; /* Skip if it's a reply and we don't have to deal with it */ if (ikev2_msg_frompeer(msg) && sa && (sa->sa_stateflags & IKED_REQ_INF)) { sa->sa_stateflags &= ~IKED_REQ_INF; if ((sa->sa_stateflags & IKED_REQ_DELETE) == 0) return (0); } if ((del = ibuf_seek(msg->msg_data, offset, sizeof(*del))) == NULL) return (-1); cnt = betoh16(del->del_nspi); sz = del->del_spisize; log_debug("%s: proto %s spisize %d nspi %d", __func__, print_map(del->del_protoid, ikev2_saproto_map), sz, cnt); buf = msgbuf + offset + sizeof(*del); len = betoh16(pld->pld_length) - sizeof(*pld) - sizeof(*del); print_hex(buf, 0, len); switch (sz) { case 4: case 8: break; default: if (ikev2_msg_frompeer(msg) && del->del_protoid == IKEV2_SAPROTO_IKE) { /* Send an empty informational response */ if ((resp = ibuf_static()) == NULL) goto done; ret = ikev2_send_ike_e(env, sa, resp, IKEV2_PAYLOAD_NONE, IKEV2_EXCHANGE_INFORMATIONAL, 1); ibuf_release(resp); sa_state(env, sa, IKEV2_STATE_CLOSED); return (ret); } log_debug("%s: invalid SPI size", __func__); return (-1); } if ((len / sz) != cnt) { log_debug("%s: invalid payload length %d/%d != %d", __func__, len, sz, cnt); return (-1); } if (ikev2_msg_frompeer(msg) && ((peersas = calloc(cnt, sizeof(struct iked_childsa *))) == NULL || (localspi = calloc(cnt, sizeof(u_int64_t))) == NULL)) { log_warn("%s", __func__); goto done; } for (i = 0; i < cnt; i++) { switch (sz) { case 4: memcpy(&spi32, buf + (i * sz), sizeof(spi32)); spi = betoh32(spi32); break; case 8: memcpy(&spi64, buf + (i * sz), sizeof(spi64)); spi = betoh64(spi64); break; } log_debug("%s: spi %s", __func__, print_spi(spi, sz)); if (peersas == NULL || sa == NULL) continue; if ((peersas[i] = childsa_lookup(sa, spi, del->del_protoid)) == NULL) { log_warnx("%s: CHILD SA doesn't exist for spi %s", __func__, print_spi(spi, del->del_spisize)); goto done; } if (ikev2_childsa_delete(env, sa, del->del_protoid, spi, &localspi[i], 0) == -1) failed++; else found++; /* * Flows are left in the require mode so that it would be * possible to quickly negotiate a new Child SA */ } /* Parsed outgoing message? */ if (!ikev2_msg_frompeer(msg)) goto done; if (sa && (sa->sa_stateflags & IKED_REQ_DELETE)) { /* Finish rekeying */ sa->sa_stateflags &= ~IKED_REQ_DELETE; ret = 0; goto done; } /* Response to the INFORMATIONAL with Delete payload */ if ((resp = ibuf_static()) == NULL) goto done; if (found) { if ((localdel = ibuf_advance(resp, sizeof(*localdel))) == NULL) goto done; localdel->del_protoid = del->del_protoid; localdel->del_spisize = del->del_spisize; localdel->del_nspi = htobe16(found); for (i = 0; i < cnt; i++) { switch (sz) { case 4: spi32 = htobe32(localspi[i]); if (ibuf_add(resp, &spi32, sizeof(spi32)) != 0) goto done; break; case 8: spi64 = htobe64(localspi[i]); if (ibuf_add(resp, &spi64, sizeof(spi64)) != 0) goto done; break; } } log_warnx("%s: deleted %d spis", __func__, found); } if (found) { ret = ikev2_send_ike_e(env, sa, resp, IKEV2_PAYLOAD_DELETE, IKEV2_EXCHANGE_INFORMATIONAL, 1); } else { /* XXX should we send an INVALID_SPI notification? */ ret = 0; } done: if (localspi) free(localspi); if (peersas) free(peersas); ibuf_release(resp); return (ret); }
/* Please forgive me for adding all the comment below. This function * has some strange bahaviors that I thought should be well explained. */ void rlctx_send_user_command(char *line) { char *cline; int length; char *rline_prompt; tgdb_request_ptr request_ptr; if (line == NULL) { /* NULL line means rl_callback_read_char received EOF */ ibuf_add(current_line, "quit"); } else { /* Add the line passed in to the current line */ ibuf_add(current_line, line); } /* Get current line, and current line length */ cline = ibuf_get(current_line); length = ibuf_length(current_line); /* Check to see if the user is escaping the line, to use a * multi line command. If so, return so that the user can * continue the command. This data should not go into the history * buffer, or be sent to gdb yet. * * Also, notice the length > 0 condition. (length == 0) can happen * when the user simply hits Enter on the keyboard. */ if (length > 0 && cline[length - 1] == '\\') { /* The \ char is for continuation only, it is not meant to be sent * to GDB as a character. */ ibuf_delchar(current_line); /* Only need to change the prompt the first time the \ char is used. * Doing it a second time would erase the real rline_last_prompt, * since the prompt has already been set to "". */ if (!rline_last_prompt) { rline_get_prompt(rline, &rline_prompt); rline_last_prompt = strdup(rline_prompt); /* GDB set's the prompt to nothing when doing continuation. * This is here just for compatibility. */ rline_set_prompt(rline, ""); } return; } /* If here, a full command has been sent. Restore the prompt. */ if (rline_last_prompt) { rline_set_prompt(rline, rline_last_prompt); free(rline_last_prompt); rline_last_prompt = NULL; } /* Don't add the enter command to the history */ if (length > 0) rline_add_history(rline, cline); request_ptr = tgdb_request_run_console_command(tgdb, cline); if (!request_ptr) logger_write_pos(logger, __FILE__, __LINE__, "rlctx_send_user_command\n"); /* Send this command to TGDB */ handle_request(tgdb, request_ptr); ibuf_clear(current_line); }