return (NULL);
#endif
}
+
+
+int
+nd_push_buffer(netdissect_options *ndo, u_char *new_buffer,
+ const u_char *new_packetp, const u_char *new_snapend)
+{
+ struct netdissect_saved_info *ndsi;
+
+ ndsi = (struct netdissect_saved_info *)malloc(sizeof(struct netdissect_saved_info));
+ if (ndsi == NULL)
+ return (0); /* fail */
+ ndsi->ndsi_buffer = new_buffer;
+ ndsi->ndsi_packetp = ndo->ndo_packetp;
+ ndsi->ndsi_snapend = ndo->ndo_snapend;
+ ndsi->ndsi_prev = ndo->ndo_buffer_stack;
+
+ ndo->ndo_packetp = new_packetp;
+ ndo->ndo_snapend = new_snapend;
+ ndo->ndo_buffer_stack = ndsi;
+
+ return (1); /* success */
+}
+
+void
+nd_pop_buffer(netdissect_options *ndo)
+{
+ struct netdissect_saved_info *ndsi;
+
+ ndsi = ndo->ndo_buffer_stack;
+ ndo->ndo_packetp = ndsi->ndsi_packetp;
+ ndo->ndo_snapend = ndsi->ndsi_snapend;
+ ndo->ndo_buffer_stack = ndsi->ndsi_prev;
+
+ free(ndsi->ndsi_buffer);
+ free(ndsi);
+}
+
+void
+nd_pop_all_buffers(netdissect_options *ndo)
+{
+ while (ndo->ndo_buffer_stack != NULL)
+ nd_pop_buffer(ndo);
+}
typedef u_int (*if_printer) IF_PRINTER_ARGS;
+/*
+ * In case the data in a buffer needs to be processed by being decrypted,
+ * decompressed, etc. before it's dissected, we can't process it in place,
+ * we have to allocate a new buffer for the processed data.
+ *
+ * We keep a stack of those buffers; when we allocate a new buffer, we
+ * push the current one onto a stack, and when we're done with the new
+ * buffer, we free the current buffer and pop the previous one off the
+ * stack.
+ *
+ * A buffer has a beginnning and end pointer, and a link to the previous
+ * buffer on the stack.
+ */
+struct netdissect_saved_info {
+ u_char *ndsi_buffer; /* pointer to allocated buffer data */
+ const u_char *ndsi_packetp; /* saved beginning of data */
+ const u_char *ndsi_snapend; /* saved end of data */
+ struct netdissect_saved_info *ndsi_prev; /* previous buffer on the stack */
+};
+
struct netdissect_options {
int ndo_bflag; /* print 4 byte ASes in ASDOT notation */
int ndo_eflag; /* print ethernet header */
const u_char *ndo_packetp;
const u_char *ndo_snapend;
+ /* stack of saved buffer information */
+ struct netdissect_saved_info *ndo_buffer_stack;
+
/* pointer to the if_printer function */
if_printer ndo_if_printer;
PRINTFLIKE_FUNCPTR(2, 3);
};
+extern int nd_push_buffer(netdissect_options *, u_char *, const u_char *,
+ const u_char *);
+extern void nd_pop_buffer(netdissect_options *);
+extern void nd_pop_all_buffers(netdissect_options *);
+
#define PT_VAT 1 /* Visual Audio Tool */
#define PT_WB 2 /* distributed White Board */
#define PT_RPC 3 /* Remote Procedure Call */
#endif
/*
- * this will adjust ndo_packetp and ndo_snapend to new buffer!
+ * This will allocate a new buffer containing the decrypted data.
+ * It returns 1 on success and 0 on failure.
+ *
+ * It will push the new buffer and the values of ndo->ndo_packetp and
+ * ndo->ndo_snapend onto the buffer stack, and change ndo->ndo_packetp
+ * and ndo->ndo_snapend to refer to the new buffer.
+ *
+ * Our caller must pop the buffer off the stack when it's finished
+ * dissecting anything in it and before it does any dissection of
+ * anything in the old buffer. That will free the new buffer.
*/
USES_APPLE_DEPRECATED_API
int esp_print_decrypt_buffer_by_ikev2(netdissect_options *ndo,
{
struct sa_list *sa;
const u_char *iv;
+ const u_char *ct;
unsigned int len;
EVP_CIPHER_CTX *ctx;
unsigned int block_size, buffer_size;
u_char *input_buffer, *output_buffer;
+ const u_char *pt;
/* initiator arg is any non-zero value */
if(initiator) initiator=1;
*/
end = end - sa->authlen;
iv = buf;
- buf = buf + sa->ivlen;
- len = end-buf;
+ ct = iv + sa->ivlen;
+ len = end-ct;
- if(end <= buf) return 0;
+ if(end <= ct) return 0;
ctx = EVP_CIPHER_CTX_new();
if (ctx == NULL)
* Copy the input data to the encrypted data buffer, and pad it
* with zeroes.
*/
- memcpy(input_buffer, buf, len);
+ memcpy(input_buffer, ct, len);
memset(input_buffer + len, 0, buffer_size - len);
/*
EVP_CIPHER_CTX_free(ctx);
/*
- * XXX - of course this is wrong, because buf is a const buffer,
- * but changing this would require a more complicated fix.
+ * Free the input buffer; we no longer need it.
*/
- memcpy(buf, output_buffer, len);
free(input_buffer);
- free(output_buffer);
- ndo->ndo_packetp = buf;
- ndo->ndo_snapend = end;
+ /*
+ * Get a pointer to the plaintext.
+ */
+ pt = output_buffer;
+
+ /*
+ * Switch to the output buffer for dissection, and save it
+ * on the buffer stack so it can be freed; our caller must
+ * pop it when done.
+ */
+ if (!nd_push_buffer(ndo, output_buffer, pt, pt + len)) {
+ free(output_buffer);
+ return 0;
+ }
return 1;
}
EVP_CIPHER_CTX *ctx;
unsigned int block_size, buffer_size;
u_char *input_buffer, *output_buffer;
+ const u_char *pt;
+ u_int ptlen;
u_int padlen;
u_int nh;
#endif
}
free(input_buffer);
EVP_CIPHER_CTX_free(ctx);
+
+ /*
+ * Pointer to the plaintext.
+ */
+ pt = output_buffer;
+
+ /*
+ * Length of the plaintext, which is the same as the length
+ * of the ciphertext.
+ */
+ ptlen = ctlen;
+
/*
- * XXX - of course this is wrong, because buf is a
- * const buffer, but changing this would require a
- * more complicated fix.
+ * Switch to the output buffer for dissection, and
+ * save it on the buffer stack so it can be freed.
*/
- memcpy(ct, output_buffer, ctlen);
- free(output_buffer);
+ if (!nd_push_buffer(ndo, output_buffer, pt, pt + ctlen)) {
+ free(output_buffer);
+ (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC,
+ "esp_print: can't push buffer on buffer stack");
+ }
+ ep = pt + ptlen;
/*
* Sanity check for pad length; if it, plus 2 for the pad
* "plaintext" is not what was being sent.
*/
padlen = GET_U_1(ep - 2);
- if (padlen + 2 > ctlen) {
+ if (padlen + 2 > ptlen) {
nd_print_trunc(ndo);
return;
}
ND_PRINT(": ");
- /* Now print the payload. */
- ip_print_demux(ndo, ct, ctlen - (padlen + 2), ver, fragmented,
+ /* Now dissect the plaintext. */
+ ip_print_demux(ndo, pt, ptlen - (padlen + 2), ver, fragmented,
ttl_hl, nh, bp2);
+
+ /* Pop the buffer, freeing it. */
+ nd_pop_buffer(ndo);
#endif
}
#ifdef HAVE_LIBCRYPTO