static void check_and_compress_jpeg(int quality, unsigned char *outbuf, const unsigned char *inbuf, int width, int height, int bufsize) { /* JPEG's are always multiples of 16, extra is ignored in AVI's */ if ((width & 0xF) || (height & 0xF)) { int i, rrowstride, jrowstride; int jwidth = PADUP(width, 16); int jheight = PADUP(height, 16); unsigned char *tmpbuf = MEM_mallocN(jwidth * jheight * 3, "avi.check_and_compress_jpeg"); /* resize the realbuf into the tmpbuf */ rrowstride = width * 3; jrowstride = jwidth * 3; for (i = 0; i < jheight; i++) { if (i < height) memcpy(&tmpbuf[i * jrowstride], &inbuf[i * rrowstride], rrowstride); else memset(&tmpbuf[i * jrowstride], 0, rrowstride); memset(&tmpbuf[i * jrowstride + rrowstride], 0, jrowstride - rrowstride); } Compress_JPEG(quality, outbuf, tmpbuf, jwidth, jheight, bufsize); MEM_freeN(tmpbuf); } else { Compress_JPEG(quality, outbuf, inbuf, width, height, bufsize); } }
void export_identity(void **p, struct tdb *tdb, int type) { struct ipsec_ref **ipr; struct sadb_ident *sadb_ident = (struct sadb_ident *) *p; if (type == PFKEYV2_IDENTITY_SRC) ipr = &tdb->tdb_srcid; else ipr = &tdb->tdb_dstid; sadb_ident->sadb_ident_len = (sizeof(struct sadb_ident) + PADUP((*ipr)->ref_len)) / sizeof(uint64_t); switch ((*ipr)->ref_type) { case IPSP_IDENTITY_PREFIX: sadb_ident->sadb_ident_type = SADB_IDENTTYPE_PREFIX; break; case IPSP_IDENTITY_FQDN: sadb_ident->sadb_ident_type = SADB_IDENTTYPE_FQDN; break; case IPSP_IDENTITY_USERFQDN: sadb_ident->sadb_ident_type = SADB_IDENTTYPE_USERFQDN; break; case IPSP_IDENTITY_CONNECTION: sadb_ident->sadb_ident_type = SADB_X_IDENTTYPE_CONNECTION; break; } *p += sizeof(struct sadb_ident); bcopy((*ipr) + 1, *p, (*ipr)->ref_len); *p += PADUP((*ipr)->ref_len); }
void export_credentials(void **p, struct tdb *tdb, int dstcred) { struct ipsec_ref **ipr; struct sadb_x_cred *sadb_cred = (struct sadb_x_cred *) *p; if (dstcred == PFKEYV2_CRED_REMOTE) ipr = &tdb->tdb_remote_cred; else ipr = &tdb->tdb_local_cred; sadb_cred->sadb_x_cred_len = (sizeof(struct sadb_x_cred) + PADUP((*ipr)->ref_len)) / sizeof(uint64_t); switch ((*ipr)->ref_type) { case IPSP_CRED_KEYNOTE: sadb_cred->sadb_x_cred_type = SADB_X_CREDTYPE_KEYNOTE; break; case IPSP_CRED_X509: sadb_cred->sadb_x_cred_type = SADB_X_CREDTYPE_X509; break; } *p += sizeof(struct sadb_x_cred); bcopy((*ipr) + 1, *p, (*ipr)->ref_len); *p += PADUP((*ipr)->ref_len); }
void export_auth(void **p, struct tdb *tdb, int dstauth) { struct ipsec_ref **ipr; struct sadb_x_cred *sadb_auth = (struct sadb_x_cred *) *p; if (dstauth == PFKEYV2_AUTH_REMOTE) ipr = &tdb->tdb_remote_auth; else ipr = &tdb->tdb_local_auth; sadb_auth->sadb_x_cred_len = (sizeof(struct sadb_x_cred) + PADUP((*ipr)->ref_len)) / sizeof(uint64_t); switch ((*ipr)->ref_type) { case IPSP_AUTH_PASSPHRASE: sadb_auth->sadb_x_cred_type = SADB_X_AUTHTYPE_PASSPHRASE; break; case IPSP_AUTH_RSA: sadb_auth->sadb_x_cred_type = SADB_X_AUTHTYPE_RSA; break; } *p += sizeof(struct sadb_x_cred); bcopy((*ipr) + 1, *p, (*ipr)->ref_len); *p += PADUP((*ipr)->ref_len); }
void *BLI_memarena_alloc(MemArena *ma, size_t size) { void *ptr; /* ensure proper alignment by rounding * size up to multiple of 8 */ size = PADUP(size, ma->align); if (UNLIKELY(size > ma->cursize)) { if (size > ma->bufsize - (ma->align - 1)) { ma->cursize = PADUP(size + 1, ma->align); } else { ma->cursize = ma->bufsize; } ma->curbuf = (ma->use_calloc ? MEM_callocN : MEM_mallocN)(ma->cursize, ma->name); BLI_linklist_prepend(&ma->bufs, ma->curbuf); memarena_curbuf_align(ma); } ptr = ma->curbuf; ma->curbuf += size; ma->cursize -= size; #ifdef WITH_MEM_VALGRIND VALGRIND_MEMPOOL_ALLOC(ma, ptr, size); #endif return ptr; }
void *BLI_memarena_alloc(MemArena *ma, int size) { void *ptr; /* ensure proper alignment by rounding * size up to multiple of 8 */ size= PADUP(size, ma->align); if (size>ma->cursize) { unsigned char *tmp; if(size > ma->bufsize - (ma->align - 1)) { ma->cursize = PADUP(size+1, ma->align); } else ma->cursize = ma->bufsize; if(ma->use_calloc) ma->curbuf= MEM_callocN(ma->cursize, ma->name); else ma->curbuf= MEM_mallocN(ma->cursize, ma->name); BLI_linklist_prepend(&ma->bufs, ma->curbuf); /* align alloc'ed memory (needed if align > 8) */ tmp = (unsigned char*)PADUP( (intptr_t) ma->curbuf, ma->align); ma->cursize -= (tmp - ma->curbuf); ma->curbuf = tmp; } ptr= ma->curbuf; ma->curbuf+= size; ma->cursize-= size; return ptr; }
/* Export PF tag information for SA */ void export_tag(void **p, struct tdb *tdb) { struct sadb_x_tag *stag = (struct sadb_x_tag *)*p; char *s = (char *)(stag + 1); pf_tag2tagname(tdb->tdb_tag, s); stag->sadb_x_tag_taglen = strlen(s) + 1; stag->sadb_x_tag_len = (sizeof(struct sadb_x_tag) + PADUP(stag->sadb_x_tag_taglen)) / sizeof(uint64_t); *p += PADUP(stag->sadb_x_tag_taglen) + sizeof(struct sadb_x_tag); }
/* * Export a struct sockaddr as an SADB_ADDRESS payload. */ void export_address(void **p, struct sockaddr *sa) { struct sadb_address *sadb_address = (struct sadb_address *) *p; sadb_address->sadb_address_len = (sizeof(struct sadb_address) + PADUP(SA_LEN(sa))) / sizeof(uint64_t); *p += sizeof(struct sadb_address); bcopy(sa, *p, SA_LEN(sa)); ((struct sockaddr *) *p)->sa_family = sa->sa_family; *p += PADUP(SA_LEN(sa)); }
/* align alloc'ed memory (needed if align > 8) */ static void memarena_curbuf_align(MemArena *ma) { unsigned char *tmp; tmp = (unsigned char *)PADUP((intptr_t)ma->curbuf, (int)ma->align); ma->cursize -= (size_t)(tmp - ma->curbuf); ma->curbuf = tmp; }
/* * Helper to export addresses from an struct sockaddr_encap. */ static void export_encap(void **p, struct sockaddr_encap *encap, int type) { struct sadb_address *saddr = (struct sadb_address *)*p; union sockaddr_union *sunion; *p += sizeof(struct sadb_address); sunion = (union sockaddr_union *)*p; switch (encap->sen_type) { case SENT_IP4: saddr->sadb_address_len = (sizeof(struct sadb_address) + PADUP(sizeof(struct sockaddr_in))) / sizeof(uint64_t); sunion->sa.sa_len = sizeof(struct sockaddr_in); sunion->sa.sa_family = AF_INET; if (type == SADB_X_EXT_SRC_FLOW || type == SADB_X_EXT_SRC_MASK) { sunion->sin.sin_addr = encap->sen_ip_src; sunion->sin.sin_port = encap->sen_sport; } else { sunion->sin.sin_addr = encap->sen_ip_dst; sunion->sin.sin_port = encap->sen_dport; } *p += PADUP(sizeof(struct sockaddr_in)); break; case SENT_IP6: saddr->sadb_address_len = (sizeof(struct sadb_address) + PADUP(sizeof(struct sockaddr_in6))) / sizeof(uint64_t); sunion->sa.sa_len = sizeof(struct sockaddr_in6); sunion->sa.sa_family = AF_INET6; if (type == SADB_X_EXT_SRC_FLOW || type == SADB_X_EXT_SRC_MASK) { sunion->sin6.sin6_addr = encap->sen_ip6_src; sunion->sin6.sin6_port = encap->sen_ip6_sport; } else { sunion->sin6.sin6_addr = encap->sen_ip6_dst; sunion->sin6.sin6_port = encap->sen_ip6_dport; } *p += PADUP(sizeof(struct sockaddr_in6)); break; } }
static int check_and_decode_jpeg(unsigned char *inbuf, unsigned char *outbuf, int width, int height, int bufsize) { /* JPEG's are always multiples of 16, extra is cropped out AVI's */ if ((width&0xF) || (height&0xF)) { int i, rrowstride, jrowstride; int jwidth= PADUP(width, 16); int jheight= PADUP(height, 16); unsigned char *tmpbuf= MEM_mallocN(jwidth*jheight*3, "avi.check_and_decode_jpeg"); int ret= Decode_JPEG(inbuf, tmpbuf, jwidth, jheight, bufsize); /* crop the tmpbuf into the real buffer */ rrowstride= width*3; jrowstride= jwidth*3; for (i=0; i<height; i++) memcpy(&outbuf[i*rrowstride], &tmpbuf[i*jrowstride], rrowstride); MEM_freeN(tmpbuf); return ret; } else { return Decode_JPEG(inbuf, outbuf, width, height, bufsize); } }
void export_key(void **p, struct tdb *tdb, int type) { struct sadb_key *sadb_key = (struct sadb_key *) *p; if (type == PFKEYV2_ENCRYPTION_KEY) { sadb_key->sadb_key_len = (sizeof(struct sadb_key) + PADUP(tdb->tdb_emxkeylen)) / sizeof(uint64_t); sadb_key->sadb_key_bits = tdb->tdb_emxkeylen * 8; *p += sizeof(struct sadb_key); bcopy(tdb->tdb_emxkey, *p, tdb->tdb_emxkeylen); *p += PADUP(tdb->tdb_emxkeylen); } else { sadb_key->sadb_key_len = (sizeof(struct sadb_key) + PADUP(tdb->tdb_amxkeylen)) / sizeof(uint64_t); sadb_key->sadb_key_bits = tdb->tdb_amxkeylen * 8; *p += sizeof(struct sadb_key); bcopy(tdb->tdb_amxkey, *p, tdb->tdb_amxkeylen); *p += PADUP(tdb->tdb_amxkeylen); } }
static void export_identity(void **p, struct ipsec_id *id) { struct sadb_ident *sadb_ident = (struct sadb_ident *) *p; sadb_ident->sadb_ident_len = (sizeof(struct sadb_ident) + PADUP(id->len)) / sizeof(uint64_t); switch (id->type) { case IPSP_IDENTITY_PREFIX: sadb_ident->sadb_ident_type = SADB_IDENTTYPE_PREFIX; break; case IPSP_IDENTITY_FQDN: sadb_ident->sadb_ident_type = SADB_IDENTTYPE_FQDN; break; case IPSP_IDENTITY_USERFQDN: sadb_ident->sadb_ident_type = SADB_IDENTTYPE_USERFQDN; break; } *p += sizeof(struct sadb_ident); bcopy(id + 1, *p, id->len); *p += PADUP(id->len); }
int pfkeyv2_parsemessage(void *p, int len, void **headers) { struct sadb_ext *sadb_ext; int i, left = len; uint64_t allow, seen = 1; struct sadb_msg *sadb_msg = (struct sadb_msg *) p; bzero(headers, (SADB_EXT_MAX + 1) * sizeof(void *)); if (left < sizeof(struct sadb_msg)) { DPRINTF(("pfkeyv2_parsemessage: message too short\n")); return (EINVAL); } headers[0] = p; if (sadb_msg->sadb_msg_len * sizeof(uint64_t) != left) { DPRINTF(("pfkeyv2_parsemessage: length not a multiple of 64\n")); return (EINVAL); } p += sizeof(struct sadb_msg); left -= sizeof(struct sadb_msg); if (sadb_msg->sadb_msg_reserved) { DPRINTF(("pfkeyv2_parsemessage: message header reserved " "field set\n")); return (EINVAL); } if (sadb_msg->sadb_msg_type > SADB_MAX) { DPRINTF(("pfkeyv2_parsemessage: message type > %d\n", SADB_MAX)); return (EINVAL); } if (!sadb_msg->sadb_msg_type) { DPRINTF(("pfkeyv2_parsemessage: message type unset\n")); return (EINVAL); } if (sadb_msg->sadb_msg_pid != curproc->p_pid) { DPRINTF(("pfkeyv2_parsemessage: bad PID value\n")); return (EINVAL); } if (sadb_msg->sadb_msg_errno) { if (left) { DPRINTF(("pfkeyv2_parsemessage: too-large error message\n")); return (EINVAL); } return (0); } if (sadb_msg->sadb_msg_type == SADB_X_PROMISC) { DPRINTF(("pfkeyv2_parsemessage: message type promiscuous\n")); return (0); } allow = sadb_exts_allowed_in[sadb_msg->sadb_msg_type]; while (left > 0) { sadb_ext = (struct sadb_ext *)p; if (left < sizeof(struct sadb_ext)) { DPRINTF(("pfkeyv2_parsemessage: extension header too " "short\n")); return (EINVAL); } i = sadb_ext->sadb_ext_len * sizeof(uint64_t); if (left < i) { DPRINTF(("pfkeyv2_parsemessage: extension header " "exceeds message length\n")); return (EINVAL); } if (sadb_ext->sadb_ext_type > SADB_EXT_MAX) { DPRINTF(("pfkeyv2_parsemessage: unknown extension " "header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (!sadb_ext->sadb_ext_type) { DPRINTF(("pfkeyv2_parsemessage: unset extension " "header\n")); return (EINVAL); } if (!(allow & (1LL << sadb_ext->sadb_ext_type))) { DPRINTF(("pfkeyv2_parsemessage: extension header %d " "not permitted on message type %d\n", sadb_ext->sadb_ext_type, sadb_msg->sadb_msg_type)); return (EINVAL); } if (headers[sadb_ext->sadb_ext_type]) { DPRINTF(("pfkeyv2_parsemessage: duplicate extension " "header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } seen |= (1LL << sadb_ext->sadb_ext_type); switch (sadb_ext->sadb_ext_type) { case SADB_EXT_SA: case SADB_X_EXT_SA2: { struct sadb_sa *sadb_sa = (struct sadb_sa *)p; if (i != sizeof(struct sadb_sa)) { DPRINTF(("pfkeyv2_parsemessage: bad header " "length for SA extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_sa->sadb_sa_state > SADB_SASTATE_MAX) { DPRINTF(("pfkeyv2_parsemessage: unknown SA " "state %d in SA extension header %d\n", sadb_sa->sadb_sa_state, sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_sa->sadb_sa_state == SADB_SASTATE_DEAD) { DPRINTF(("pfkeyv2_parsemessage: cannot set SA " "state to dead, SA extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_sa->sadb_sa_encrypt > SADB_EALG_MAX) { DPRINTF(("pfkeyv2_parsemessage: unknown " "encryption algorithm %d in SA extension " "header %d\n", sadb_sa->sadb_sa_encrypt, sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_sa->sadb_sa_auth > SADB_AALG_MAX) { DPRINTF(("pfkeyv2_parsemessage: unknown " "authentication algorithm %d in SA " "extension header %d\n", sadb_sa->sadb_sa_auth, sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_sa->sadb_sa_replay > 32) { DPRINTF(("pfkeyv2_parsemessage: unsupported " "replay window size %d in SA extension " "header %d\n", sadb_sa->sadb_sa_replay, sadb_ext->sadb_ext_type)); return (EINVAL); } } break; case SADB_X_EXT_PROTOCOL: case SADB_X_EXT_FLOW_TYPE: if (i != sizeof(struct sadb_protocol)) { DPRINTF(("pfkeyv2_parsemessage: bad " "PROTOCOL/FLOW header length in extension " "header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } break; case SADB_X_EXT_POLICY: if (i != sizeof(struct sadb_x_policy)) { DPRINTF(("pfkeyv2_parsemessage: bad POLICY " "header length\n")); return (EINVAL); } break; case SADB_EXT_LIFETIME_CURRENT: case SADB_EXT_LIFETIME_HARD: case SADB_EXT_LIFETIME_SOFT: case SADB_X_EXT_LIFETIME_LASTUSE: if (i != sizeof(struct sadb_lifetime)) { DPRINTF(("pfkeyv2_parsemessage: bad header " "length for LIFETIME extension header " "%d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } break; case SADB_EXT_ADDRESS_SRC: case SADB_EXT_ADDRESS_DST: case SADB_X_EXT_SRC_MASK: case SADB_X_EXT_DST_MASK: case SADB_X_EXT_SRC_FLOW: case SADB_X_EXT_DST_FLOW: case SADB_X_EXT_DST2: case SADB_EXT_ADDRESS_PROXY: { struct sadb_address *sadb_address = (struct sadb_address *)p; struct sockaddr *sa = (struct sockaddr *)(p + sizeof(struct sadb_address)); if (i < sizeof(struct sadb_address) + sizeof(struct sockaddr)) { DPRINTF(("pfkeyv2_parsemessage: bad ADDRESS " "extension header %d length\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_address->sadb_address_reserved) { DPRINTF(("pfkeyv2_parsemessage: ADDRESS " "extension header %d reserved field set\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (sa->sa_len && (i != sizeof(struct sadb_address) + PADUP(sa->sa_len))) { DPRINTF(("pfkeyv2_parsemessage: bad sockaddr " "length field in ADDRESS extension " "header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } switch (sa->sa_family) { case AF_INET: if (sizeof(struct sadb_address) + PADUP(sizeof(struct sockaddr_in)) != i) { DPRINTF(("pfkeyv2_parsemessage: " "invalid ADDRESS extension header " "%d length\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (sa->sa_len != sizeof(struct sockaddr_in)) { DPRINTF(("pfkeyv2_parsemessage: bad " "sockaddr_in length in ADDRESS " "extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } /* Only check the right pieces */ switch (sadb_ext->sadb_ext_type) { case SADB_X_EXT_SRC_MASK: case SADB_X_EXT_DST_MASK: case SADB_X_EXT_SRC_FLOW: case SADB_X_EXT_DST_FLOW: break; default: if (((struct sockaddr_in *)sa)->sin_port) { DPRINTF(("pfkeyv2_parsemessage" ": port field set in " "sockaddr_in of ADDRESS " "extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } break; } { char zero[sizeof(((struct sockaddr_in *)sa)->sin_zero)]; bzero(zero, sizeof(zero)); if (bcmp(&((struct sockaddr_in *)sa)->sin_zero, zero, sizeof(zero))) { DPRINTF(("pfkeyv2_parsemessage" ": reserved sockaddr_in " "field non-zero'ed in " "ADDRESS extension header " "%d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } } break; #if INET6 case AF_INET6: if (i != sizeof(struct sadb_address) + PADUP(sizeof(struct sockaddr_in6))) { DPRINTF(("pfkeyv2_parsemessage: " "invalid sockaddr_in6 length in " "ADDRESS extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (sa->sa_len != sizeof(struct sockaddr_in6)) { DPRINTF(("pfkeyv2_parsemessage: bad " "sockaddr_in6 length in ADDRESS " "extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (((struct sockaddr_in6 *)sa)->sin6_flowinfo) { DPRINTF(("pfkeyv2_parsemessage: " "flowinfo field set in " "sockaddr_in6 of ADDRESS " "extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } /* Only check the right pieces */ switch (sadb_ext->sadb_ext_type) { case SADB_X_EXT_SRC_MASK: case SADB_X_EXT_DST_MASK: case SADB_X_EXT_SRC_FLOW: case SADB_X_EXT_DST_FLOW: break; default: if (((struct sockaddr_in6 *)sa)->sin6_port) { DPRINTF(("pfkeyv2_parsemessage" ": port field set in " "sockaddr_in6 of ADDRESS " "extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } break; } break; #endif /* INET6 */ default: if (sadb_msg->sadb_msg_satype == SADB_X_SATYPE_TCPSIGNATURE && sa->sa_family == 0) break; DPRINTF(("pfkeyv2_parsemessage: unknown " "address family %d in ADDRESS extension " "header %d\n", sa->sa_family, sadb_ext->sadb_ext_type)); return (EINVAL); } } break; case SADB_EXT_KEY_AUTH: case SADB_EXT_KEY_ENCRYPT: { struct sadb_key *sadb_key = (struct sadb_key *)p; if (i < sizeof(struct sadb_key)) { DPRINTF(("pfkeyv2_parsemessage: bad header " "length in KEY extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (!sadb_key->sadb_key_bits) { DPRINTF(("pfkeyv2_parsemessage: key length " "unset in KEY extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (((sadb_key->sadb_key_bits + 63) / 64) * sizeof(uint64_t) != i - sizeof(struct sadb_key)) { DPRINTF(("pfkeyv2_parsemessage: invalid key " "length in KEY extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_key->sadb_key_reserved) { DPRINTF(("pfkeyv2_parsemessage: reserved field" " set in KEY extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } } break; case SADB_X_EXT_LOCAL_AUTH: case SADB_X_EXT_REMOTE_AUTH: { struct sadb_x_cred *sadb_cred = (struct sadb_x_cred *)p; if (i < sizeof(struct sadb_x_cred)) { DPRINTF(("pfkeyv2_parsemessage: bad header " "length for AUTH extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_cred->sadb_x_cred_type > SADB_X_AUTHTYPE_MAX) { DPRINTF(("pfkeyv2_parsemessage: unknown auth " "type %d in AUTH extension header %d\n", sadb_cred->sadb_x_cred_type, sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_cred->sadb_x_cred_reserved) { DPRINTF(("pfkeyv2_parsemessage: reserved field" " set in AUTH extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } } break; case SADB_X_EXT_LOCAL_CREDENTIALS: case SADB_X_EXT_REMOTE_CREDENTIALS: { struct sadb_x_cred *sadb_cred = (struct sadb_x_cred *)p; if (i < sizeof(struct sadb_x_cred)) { DPRINTF(("pfkeyv2_parsemessage: bad header " "length of CREDENTIALS extension header " "%d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_cred->sadb_x_cred_type > SADB_X_CREDTYPE_MAX) { DPRINTF(("pfkeyv2_parsemessage: unknown " "credential type %d in CREDENTIALS " "extension header %d\n", sadb_cred->sadb_x_cred_type, sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_cred->sadb_x_cred_reserved) { DPRINTF(("pfkeyv2_parsemessage: reserved " "field set in CREDENTIALS extension " "header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } } break; case SADB_EXT_IDENTITY_SRC: case SADB_EXT_IDENTITY_DST: { struct sadb_ident *sadb_ident = (struct sadb_ident *)p; if (i < sizeof(struct sadb_ident)) { DPRINTF(("pfkeyv2_parsemessage: bad header " "length of IDENTITY extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) { DPRINTF(("pfkeyv2_parsemessage: unknown " "identity type %d in IDENTITY extension " "header %d\n", sadb_ident->sadb_ident_type, sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_ident->sadb_ident_reserved) { DPRINTF(("pfkeyv2_parsemessage: reserved " "field set in IDENTITY extension header " "%d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (i > sizeof(struct sadb_ident)) { char *c = (char *)(p + sizeof(struct sadb_ident)); int j; if (*(char *)(p + i - 1)) { DPRINTF(("pfkeyv2_parsemessage: non " "NUL-terminated identity in " "IDENTITY extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } j = PADUP(strlen(c) + 1) + sizeof(struct sadb_ident); if (i != j) { DPRINTF(("pfkeyv2_parsemessage: actual" " identity length does not match " "expected length in identity " "extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } } } break; case SADB_EXT_SENSITIVITY: { struct sadb_sens *sadb_sens = (struct sadb_sens *)p; if (i < sizeof(struct sadb_sens)) { DPRINTF(("pfkeyv2_parsemessage: bad header " "length for SENSITIVITY extension " "header\n")); return (EINVAL); } if (i != (sadb_sens->sadb_sens_sens_len + sadb_sens->sadb_sens_integ_len) * sizeof(uint64_t) + sizeof(struct sadb_sens)) { DPRINTF(("pfkeyv2_parsemessage: bad payload " "length for SENSITIVITY extension " "header\n")); return (EINVAL); } } break; case SADB_EXT_PROPOSAL: { struct sadb_prop *sadb_prop = (struct sadb_prop *)p; if (i < sizeof(struct sadb_prop)) { DPRINTF(("pfkeyv2_parsemessage: bad PROPOSAL " "header length\n")); return (EINVAL); } if (sadb_prop->sadb_prop_reserved) { DPRINTF(("pfkeyv2_parsemessage: reserved field" "set in PROPOSAL extension header\n")); return (EINVAL); } if ((i - sizeof(struct sadb_prop)) % sizeof(struct sadb_comb)) { DPRINTF(("pfkeyv2_parsemessage: bad proposal " "length\n")); return (EINVAL); } { struct sadb_comb *sadb_comb = (struct sadb_comb *)(p + sizeof(struct sadb_prop)); int j; for (j = 0; j < (i - sizeof(struct sadb_prop))/ sizeof(struct sadb_comb); j++) { if (sadb_comb->sadb_comb_auth > SADB_AALG_MAX) { DPRINTF(("pfkeyv2_parsemessage" ": unknown authentication " "algorithm %d in " "PROPOSAL\n", sadb_comb->sadb_comb_auth)); return (EINVAL); } if (sadb_comb->sadb_comb_encrypt > SADB_EALG_MAX) { DPRINTF(("pfkeyv2_parsemessage" ": unknown encryption " "algorithm %d in " "PROPOSAL\n", sadb_comb->sadb_comb_encrypt)); return (EINVAL); } if (sadb_comb->sadb_comb_reserved) { DPRINTF(("pfkeyv2_parsemessage" ": reserved field set in " "COMB header\n")); return (EINVAL); } } } } break; case SADB_EXT_SUPPORTED_AUTH: case SADB_EXT_SUPPORTED_ENCRYPT: case SADB_X_EXT_SUPPORTED_COMP: { struct sadb_supported *sadb_supported = (struct sadb_supported *)p; int j; if (i < sizeof(struct sadb_supported)) { DPRINTF(("pfkeyv2_parsemessage: bad header " "length for SUPPORTED extension header " "%d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_supported->sadb_supported_reserved) { DPRINTF(("pfkeyv2_parsemessage: reserved " "field set in SUPPORTED extension " "header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } { struct sadb_alg *sadb_alg = (struct sadb_alg *)(p + sizeof(struct sadb_supported)); int max_alg; max_alg = sadb_ext->sadb_ext_type == SADB_EXT_SUPPORTED_AUTH ? SADB_AALG_MAX : SADB_EXT_SUPPORTED_ENCRYPT ? SADB_EALG_MAX : SADB_X_CALG_MAX; for (j = 0; j < sadb_supported->sadb_supported_len - 1; j++) { if (sadb_alg->sadb_alg_id > max_alg) { DPRINTF(("pfkeyv2_parsemessage" ": unknown algorithm %d " "in SUPPORTED extension " "header %d\n", sadb_alg->sadb_alg_id, sadb_ext->sadb_ext_type)); return (EINVAL); } if (sadb_alg->sadb_alg_reserved) { DPRINTF(("pfkeyv2_parsemessage" ": reserved field set in " "supported algorithms " "header inside SUPPORTED " "extension header %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } sadb_alg++; } } } break; case SADB_EXT_SPIRANGE: { struct sadb_spirange *sadb_spirange = (struct sadb_spirange *)p; if (i != sizeof(struct sadb_spirange)) { DPRINTF(("pfkeyv2_parsemessage: bad header " "length of SPIRANGE extension header\n")); return (EINVAL); } if (sadb_spirange->sadb_spirange_min > sadb_spirange->sadb_spirange_max) { DPRINTF(("pfkeyv2_parsemessage: bad SPI " "range\n")); return (EINVAL); } } break; case SADB_X_EXT_UDPENCAP: if (i != sizeof(struct sadb_x_udpencap)) { DPRINTF(("pfkeyv2_parsemessage: bad UDPENCAP " "header length\n")); return (EINVAL); } break; #if NPF > 0 case SADB_X_EXT_TAG: if (i < sizeof(struct sadb_x_tag)) { DPRINTF(("pfkeyv2_parsemessage: " "TAG extension header too small")); return (EINVAL); } if (i > (sizeof(struct sadb_x_tag) + PF_TAG_NAME_SIZE)) { DPRINTF(("pfkeyv2_parsemessage: " "TAG extension header too long")); return (EINVAL); } break; #endif default: DPRINTF(("pfkeyv2_parsemessage: unknown extension " "header type %d\n", sadb_ext->sadb_ext_type)); return (EINVAL); } headers[sadb_ext->sadb_ext_type] = p; p += i; left -= i; } if (left) { DPRINTF(("pfkeyv2_parsemessage: message too long\n")); return (EINVAL); } { uint64_t required; required = sadb_exts_required_in[sadb_msg->sadb_msg_type]; if ((seen & required) != required) { DPRINTF(("pfkeyv2_parsemessage: required fields " "missing\n")); return (EINVAL); } } switch (((struct sadb_msg *)headers[0])->sadb_msg_type) { case SADB_UPDATE: if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { DPRINTF(("pfkeyv2_parsemessage: updating non-mature " "SA prohibited\n")); return (EINVAL); } break; case SADB_ADD: if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state != SADB_SASTATE_MATURE) { DPRINTF(("pfkeyv2_parsemessage: adding non-mature " "SA prohibited\n")); return (EINVAL); } break; } return (0); }