/** * Unpack a message whack received * * @param wp The whack message * @return err_t */ err_t unpack_whack_msg (struct whackpacker *wp) { err_t ugh = NULL; if (wp->str_next > wp->str_roof) { ugh = builddiag("ignoring truncated message from whack: got %d bytes; expected %u" , (int) wp->n, (unsigned) sizeof(wp->msg)); } if (!unpack_str(wp, &wp->msg->name) /* string 1 */ || !unpack_str(wp, &wp->msg->left.id) /* string 2 */ || !unpack_str(wp, &wp->msg->left.cert) /* string 3 */ || !unpack_str(wp, &wp->msg->left.ca) /* string 4 */ || !unpack_str(wp, &wp->msg->left.groups) /* string 5 */ || !unpack_str(wp, &wp->msg->left.updown) /* string 6 */ || !unpack_str(wp, &wp->msg->left.virt) /* string 7 */ || !unpack_str(wp, &wp->msg->right.id) /* string 8 */ || !unpack_str(wp, &wp->msg->right.cert) /* string 9 */ || !unpack_str(wp, &wp->msg->right.ca) /* string 10 */ || !unpack_str(wp, &wp->msg->right.groups)/* string 11 */ || !unpack_str(wp, &wp->msg->right.updown)/* string 12 */ || !unpack_str(wp, &wp->msg->right.virt) /* string 13 */ || !unpack_str(wp, &wp->msg->keyid) /* string 14 */ || !unpack_str(wp, &wp->msg->myid) /* string 15 */ || !unpack_str(wp, &wp->msg->ike) /* string 16 */ || !unpack_str(wp, &wp->msg->esp) /* string 17 */ || !unpack_str(wp, &wp->msg->tpmeval) /* string 18 */ || !unpack_str(wp, &wp->msg->left.xauth_name) /* string 19 */ || !unpack_str(wp, &wp->msg->right.xauth_name) /* string 20 */ || !unpack_str(wp, &wp->msg->connalias) /* string 21 */ || !unpack_str(wp, &wp->msg->left.host_addr_name) /* string 22 */ || !unpack_str(wp, &wp->msg->right.host_addr_name) /* string 23 */ || !unpack_str(wp, &wp->msg->string1) /* string 24 */ || !unpack_str(wp, &wp->msg->string2) /* string 25 */ || !unpack_str(wp, &wp->msg->string3) /* string 26 */ || !unpack_str(wp, &wp->msg->dnshostname) /* string 27 ? */ #ifdef HAVE_LABELED_IPSEC || !unpack_str(wp, &wp->msg->policy_label) /* string 28 */ #endif || wp->str_roof - wp->str_next != (ptrdiff_t)wp->msg->keyval.len) /* check chunk */ { ugh = "message from whack contains bad string"; } return ugh; }
/******************************************************************************* 函数名称: init_ws_ctl_socket 功能描述: 初始化web_services control套接字 输入参数: 输出参数: 无 返 回 值 : err_t:返回错误信息,成功返回NULL -------------------------------------------------------------------------------- 最近一次修改记录 : 修改作者: tiangu 修改目的: 创建新函数 修改日期: 2010-4-20 *******************************************************************************/ err_t init_ws_ctl_socket(void) { err_t failed = NULL; delete_ws_ctl_socket(); /* preventative medicine */ ws_ctl_fd = safe_socket(AF_UNIX, SOCK_STREAM, 0); int size = offsetof(struct sockaddr_un, sun_path) + strlen(ws_ctl_addr.sun_path); if (ws_ctl_fd == -1) { failed = "create"; } else if (setsockopt(ws_ctl_fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof(on)) < 0) { failed = "setsockopt"; } else { mode_t ou = umask(0); if (bind(ws_ctl_fd, (struct sockaddr *)&ws_ctl_addr, size) < 0) { failed = "bind"; } umask(ou); } if (failed == NULL && listen(ws_ctl_fd, 5) < 0) { failed = "listen() on"; } return failed == NULL? NULL : builddiag("could not %s ws_ctl socket: %d %s" , failed, errno, strerror(errno)); }
/** * Unpack a message whack received * * @param wp The whack message * @return err_t */ err_t unpack_whack_msg (struct whackpacker *wp) { err_t ugh = NULL; if (wp->str_next > wp->str_roof) { ugh = builddiag("ignoring truncated message from whack: got %d bytes; expected %u" , (int) wp->n, (unsigned) sizeof(wp->msg)); } if (!unpack_str(wp, &wp->msg->name) /* string 1 */ || !unpack_str(wp, &wp->msg->left.id) /* string 2 */ || !unpack_str(wp, &wp->msg->left.cert) /* string 3 */ || !unpack_str(wp, &wp->msg->left.ca) /* string 4 */ || !unpack_str(wp, &wp->msg->left.groups) /* string 5 */ || !unpack_str(wp, &wp->msg->left.updown) /* string 6 */ #ifdef VIRTUAL_IP || !unpack_str(wp,&wp->msg->left.virt) /* string 7 */ #endif || !unpack_str(wp, &wp->msg->right.id) /* string 8 */ || !unpack_str(wp, &wp->msg->right.cert) /* string 9 */ || !unpack_str(wp, &wp->msg->right.ca) /* string 10 */ || !unpack_str(wp, &wp->msg->right.groups)/* string 11 */ || !unpack_str(wp, &wp->msg->right.updown)/* string 12 */ #ifdef VIRTUAL_IP || !unpack_str(wp, &wp->msg->right.virt) /* string 13 */ #endif || !unpack_str(wp, &wp->msg->keyid) /* string 14 */ || !unpack_str(wp, &wp->msg->myid) /* string 15 */ || !unpack_str(wp, &wp->msg->ike) /* string 16 */ || !unpack_str(wp, &wp->msg->esp) /* string 17 */ || wp->str_roof - wp->str_next != (ptrdiff_t)wp->msg->keyval.len) /* check chunk */ { ugh = "message from whack contains bad string"; } return ugh; }
bool in_struct(void *struct_ptr, struct_desc *sd , pb_stream *ins, pb_stream *obj_pbs) { err_t ugh = NULL; u_int8_t *cur = ins->cur; if (ins->roof - cur < (ptrdiff_t)sd->size) { ugh = builddiag("not enough room in input packet for %s", sd->name); } else { u_int8_t *roof = cur + sd->size; /* may be changed by a length field */ u_int8_t *outp = struct_ptr; bool immediate = FALSE; field_desc *fp; for (fp = sd->fields; ugh == NULL; fp++) { size_t i = fp->size; passert(ins->roof - cur >= (ptrdiff_t)i); passert(cur - ins->cur <= (ptrdiff_t)(sd->size - i)); passert(outp - (cur - ins->cur) == struct_ptr); #if 0 DBG(DBG_PARSING, DBG_log("%d %s" , (int) (cur - ins->cur), fp->name == NULL? "" : fp->name)); #endif switch (fp->field_type) { case ft_mbz: /* must be zero */ for (; i != 0; i--) { if (*cur++ != 0) { ugh = builddiag("byte %d of %s must be zero, but is not" , (int) (cur - ins->cur), sd->name); break; } *outp++ = '\0'; /* probably redundant */ } break; case ft_nat: /* natural number (may be 0) */ case ft_len: /* length of this struct and any following crud */ case ft_lv: /* length/value field of attribute */ case ft_enum: /* value from an enumeration */ case ft_loose_enum: /* value from an enumeration with only some names known */ case ft_af_enum: /* Attribute Format + value from an enumeration */ case ft_set: /* bits representing set */ { u_int32_t n = 0; for (; i != 0; i--) n = (n << BITS_PER_BYTE) | *cur++; switch (fp->field_type) { case ft_len: /* length of this struct and any following crud */ case ft_lv: /* length/value field of attribute */ { u_int32_t len = fp->field_type == ft_len? n : immediate? sd->size : n + sd->size; if (len < sd->size) { ugh = builddiag("%s of %s is smaller than minimum" , fp->name, sd->name); } else if (pbs_left(ins) < len) { ugh = builddiag("%s of %s is larger than can fit" , fp->name, sd->name); } else { roof = ins->cur + len; } break; } case ft_af_enum: /* Attribute Format + value from an enumeration */ if ((n & ISAKMP_ATTR_AF_MASK) == ISAKMP_ATTR_AF_TV) immediate = TRUE; /* FALL THROUGH */ case ft_enum: /* value from an enumeration */ if (enum_name(fp->desc, n) == NULL) { ugh = builddiag("%s of %s has an unknown value: %lu" , fp->name, sd->name, (unsigned long)n); } /* FALL THROUGH */ case ft_loose_enum: /* value from an enumeration with only some names known */ break; case ft_set: /* bits representing set */ if (!testset(fp->desc, n)) { ugh = builddiag("bitset %s of %s has unknown member(s): %s" , fp->name, sd->name, bitnamesof(fp->desc, n)); } break; default: break; } i = fp->size; switch (i) { case 8/BITS_PER_BYTE: *(u_int8_t *)outp = n; break; case 16/BITS_PER_BYTE: *(u_int16_t *)outp = n; break; case 32/BITS_PER_BYTE: *(u_int32_t *)outp = n; break; default: impossible(); } outp += i; break; } case ft_raw: /* bytes to be left in network-order */ for (; i != 0; i--) { *outp++ = *cur++; } break; case ft_end: /* end of field list */ passert(cur == ins->cur + sd->size); if (obj_pbs != NULL) { init_pbs(obj_pbs, ins->cur, roof - ins->cur, sd->name); obj_pbs->container = ins; obj_pbs->desc = sd; obj_pbs->cur = cur; } ins->cur = roof; DBG(DBG_PARSING , DBG_prefix_print_struct(ins, "parse ", struct_ptr, sd, TRUE)); return TRUE; default: impossible(); } } } /* some failure got us here: report it */ loglog(RC_LOG_SERIOUS, ugh); return FALSE; }
/* Handle a kernel request. Supposedly, there's a message in * the kernelsock socket. */ void whack_handle(int whackctlfd) { struct whack_message msg; struct sockaddr_un whackaddr; int whackaddrlen = sizeof(whackaddr); int whackfd = accept(whackctlfd, (struct sockaddr *)&whackaddr, &whackaddrlen); ssize_t n; if (whackfd < 0) { log_errno((e, "accept() failed in whack_handle()")); return; } n = read(whackfd, &msg, sizeof(msg)); if (n == -1) { log_errno((e, "read() failed in whack_handle()")); close(whackfd); return; } whack_log_fd = whackfd; /* sanity check message */ { err_t ugh = NULL; next_str = msg.string; str_roof = (char *)&msg + n; if (next_str > str_roof) { ugh = builddiag("truncated message from whack: got %d bytes; expected %d. Message ignored." , n, (int) sizeof(msg)); } else if (msg.magic != WHACK_MAGIC) { ugh = builddiag("message from whack has bad magic %d; should be %d; probably wrong version. Message ignored" , msg.magic, WHACK_MAGIC); } else if (!unpack_str(&msg.name) /* string 1 */ || !unpack_str(&msg.left.id) /* string 2 */ || !unpack_str(&msg.left.cert) /* string 3 */ || !unpack_str(&msg.left.updown) /* string 4 */ #ifdef VIRTUAL_IP || !unpack_str(&msg.left.virt) #endif || !unpack_str(&msg.right.id) /* string 5 */ || !unpack_str(&msg.right.cert) /* string 6 */ || !unpack_str(&msg.right.updown) /* string 7 */ #ifdef VIRTUAL_IP || !unpack_str(&msg.right.virt) #endif || !unpack_str(&msg.keyid) /* string 8 */ || !unpack_str(&msg.ike) /* string 9 */ || !unpack_str(&msg.esp) /* string 10 */ || !unpack_str(&msg.dnshostname) /* string 11 */ || str_roof - next_str != (ptrdiff_t)msg.keyval.len) /* check chunk */ { ugh = "message from whack contains bad string"; } else { msg.keyval.ptr = next_str; /* grab chunk */ } if (ugh != NULL) { loglog(RC_BADWHACKMESSAGE, "%s", ugh); whack_log_fd = NULL_FD; close(whackfd); return; } } if (msg.whack_options) { #ifdef DEBUG if (msg.name == NULL) { /* we do a two-step so that if either old or new would * cause the message to print, it will be printed. */ cur_debugging |= msg.debugging; DBG(DBG_CONTROL , DBG_log("base debugging = %s" , bitnamesof(debug_bit_names, msg.debugging))); cur_debugging = base_debugging = msg.debugging; } else if (!msg.whack_connection) { struct connection *c = con_by_name(msg.name, TRUE); if (c != NULL) { c->extra_debugging = msg.debugging; DBG(DBG_CONTROL , DBG_log("\"%s\" extra_debugging = %s" , c->name , bitnamesof(debug_bit_names, c->extra_debugging))); } } #endif } /* Deleting combined with adding a connection works as replace. * To make this more useful, in only this combination, * delete will silently ignore the lack of the connection. */ if (msg.whack_delete) { struct connection *c = con_by_name(msg.name, !msg.whack_connection); /* note: this is a "while" because road warrior * leads to multiple connections with the same name. */ for (; c != NULL; c = con_by_name(msg.name, FALSE)) delete_connection(c); } if (msg.whack_deletestate) { struct state *st = state_with_serialno(msg.whack_deletestateno); if (st == NULL) { loglog(RC_UNKNOWN_NAME, "no state #%lu to delete" , msg.whack_deletestateno); } else { delete_state(st); } } if (msg.whack_connection) add_connection(&msg); /* process "listen" before any operation that could require it */ if (msg.whack_listen) { log("listening for IKE messages"); listening = TRUE; find_ifaces(); load_preshared_secrets(); } if (msg.whack_unlisten) { log("no longer listening for IKE messages"); listening = FALSE; } if (msg.whack_reread & REREAD_SECRETS) { load_preshared_secrets(); } if (msg.whack_reread & REREAD_MYCERT) { load_mycert(); } if (msg.whack_reread & REREAD_CACERTS) { load_cacerts(); } if (msg.whack_reread & REREAD_CRLS) { load_crls(); } if (msg.whack_list & LIST_PUBKEYS) { list_public_keys(msg.whack_utc); } if (msg.whack_list & LIST_CERTS) { list_certs(msg.whack_utc); } if (msg.whack_list & LIST_CACERTS) { list_cacerts(msg.whack_utc); } if (msg.whack_list & LIST_CRLS) { list_crls(msg.whack_utc); } if (msg.whack_key) { /* add a public key */ struct id keyid; err_t ugh = atoid(msg.keyid, &keyid); if (ugh != NULL) { loglog(RC_BADID, "bad --keyid \"%s\": %s", msg.keyid, ugh); } else { if (!msg.whack_addkey) delete_public_keys(&keyid, msg.pubkey_alg); if (msg.keyval.len == 0) { struct key_add_continuation *kc = alloc_thing(struct key_add_continuation , "key add continuation"); int wfd = dup_any(whackfd); kc->whack_fd = wfd; ugh = start_adns_query(&keyid , NULL , T_KEY , key_add_continue , &kc->ac); if (ugh != NULL) { key_add_ugh(&keyid, ugh); close_any(wfd); } } else { ugh = add_public_key(&keyid, DAL_LOCAL, msg.pubkey_alg , &msg.keyval, &pubkeys); if (ugh != NULL) loglog(RC_LOG_SERIOUS, "%s", ugh); } } }