static void print_packet(FILE *fp, RADIUS_PACKET *packet) { VALUE_PAIR *vp; vp_cursor_t cursor; if (!packet) { fprintf(fp, "\n"); return; } fprintf(fp, "%s\n", fr_packet_codes[packet->code]); for (vp = fr_cursor_init(&cursor, &packet->vps); vp; vp = fr_cursor_next(&cursor)) { /* * Take this opportunity to verify all the VALUE_PAIRs are still valid. */ if (!talloc_get_type(vp, VALUE_PAIR)) { ERROR("Expected VALUE_PAIR pointer got \"%s\"", talloc_get_name(vp)); fr_log_talloc_report(vp); rad_assert(0); } vp_print(fp, vp); } fflush(fp); }
/* * Print a whole list of attributes, indented by a TAB * and with a newline at the end. */ void vp_printlist(FILE *fp, VALUE_PAIR *vp) { for (; vp; vp = vp->next) { fprintf(fp, "\t"); vp_print(fp, vp); fprintf(fp, "\n"); } }
/** * @brief print a list of valuepairs to stderr or error log */ void debug_pair_list(VALUE_PAIR *vp) { if (!vp || !debug_flag || !fr_log_fp) return; while (vp) { vp_print(fr_log_fp, vp); vp = vp->next; } fflush(fr_log_fp); }
/** Print a list of attributes and enumv * * @param fp to output to. * @param const_vp to print. */ void vp_printlist(FILE *fp, VALUE_PAIR const *const_vp) { VALUE_PAIR *vp; vp_cursor_t cursor; memcpy(&vp, &const_vp, sizeof(vp)); /* const work-arounds */ for (vp = fr_cursor_init(&cursor, &vp); vp; vp = fr_cursor_next(&cursor)) { vp_print(fp, vp); } }
/* * Wrapper for VPs allocated on the stack. */ static void detail_vp_print(TALLOC_CTX *ctx, FILE *out, VALUE_PAIR const *stacked) { VALUE_PAIR *vp; vp = talloc(ctx, VALUE_PAIR); if (!vp) return; memcpy(vp, stacked, sizeof(*vp)); vp_print(out, vp); talloc_free(vp); }
/** Print a list of valuepairs to stderr or error log. * * @param[in] vp to print. */ void debug_pair_list(VALUE_PAIR *vp) { vp_cursor_t cursor; if (!vp || !debug_flag || !fr_log_fp) return; for (vp = fr_cursor_init(&cursor, &vp); vp; vp = fr_cursor_next(&cursor)) { vp_print(fr_log_fp, vp); } fflush(fr_log_fp); }
/** Print a list of valuepairs to stderr or error log. * * @param[in] vp to print. */ void debug_pair_list(VALUE_PAIR *vp) { vp_cursor_t cursor; if (!vp || !debug_flag || !fr_log_fp) return; for (vp = paircursor(&cursor, &vp); vp; vp = pairnext(&cursor)) { /* * Take this opportunity to verify all the VALUE_PAIRs are still valid. */ if (!talloc_get_type(vp, VALUE_PAIR)) { ERROR("Expected VALUE_PAIR pointer got \"%s\"", talloc_get_name(vp)); log_talloc_report(vp); rad_assert(0); } vp_print(fr_log_fp, vp); } fflush(fr_log_fp); }
/** * @brief print a single valuepair to stderr or error log */ void debug_pair(VALUE_PAIR *vp) { if (!vp || !debug_flag || !fr_log_fp) return; vp_print(fr_log_fp, vp); }
static REQUEST *request_setup(FILE *fp) { VALUE_PAIR *vp; REQUEST *request; vp_cursor_t cursor; /* * Create and initialize the new request. */ request = request_alloc(NULL); request->packet = rad_alloc(request, false); if (!request->packet) { ERROR("No memory"); talloc_free(request); return NULL; } request->reply = rad_alloc(request, false); if (!request->reply) { ERROR("No memory"); talloc_free(request); return NULL; } request->listener = listen_alloc(request); request->client = client_alloc(request); request->number = 0; request->master_state = REQUEST_ACTIVE; request->child_state = REQUEST_RUNNING; request->handle = NULL; request->server = talloc_typed_strdup(request, "default"); request->root = &main_config; /* * Read packet from fp */ if (readvp2(request->packet, &request->packet->vps, fp, &filedone) < 0) { fr_perror("unittest"); talloc_free(request); return NULL; } /* * Set the defaults for IPs, etc. */ request->packet->code = PW_CODE_ACCESS_REQUEST; request->packet->src_ipaddr.af = AF_INET; request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK); request->packet->src_port = 18120; request->packet->dst_ipaddr.af = AF_INET; request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK); request->packet->dst_port = 1812; /* * Copied from radclient */ #if 1 /* * Fix up Digest-Attributes issues */ for (vp = fr_cursor_init(&cursor, &request->packet->vps); vp; vp = fr_cursor_next(&cursor)) { /* * Double quoted strings get marked up as xlat expansions, * but we don't support that here. */ if (vp->type == VT_XLAT) { vp->vp_strvalue = vp->value.xlat; vp->value.xlat = NULL; vp->type = VT_DATA; } if (!vp->da->vendor) switch (vp->da->attr) { default: break; /* * Allow it to set the packet type in * the attributes read from the file. */ case PW_PACKET_TYPE: request->packet->code = vp->vp_integer; break; case PW_PACKET_DST_PORT: request->packet->dst_port = (vp->vp_integer & 0xffff); break; case PW_PACKET_DST_IP_ADDRESS: request->packet->dst_ipaddr.af = AF_INET; request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; break; case PW_PACKET_DST_IPV6_ADDRESS: request->packet->dst_ipaddr.af = AF_INET6; request->packet->dst_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr; break; case PW_PACKET_SRC_PORT: request->packet->src_port = (vp->vp_integer & 0xffff); break; case PW_PACKET_SRC_IP_ADDRESS: request->packet->src_ipaddr.af = AF_INET; request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = vp->vp_ipaddr; break; case PW_PACKET_SRC_IPV6_ADDRESS: request->packet->src_ipaddr.af = AF_INET6; request->packet->src_ipaddr.ipaddr.ip6addr = vp->vp_ipv6addr; break; case PW_CHAP_PASSWORD: { int i, already_hex = 0; /* * If it's 17 octets, it *might* be already encoded. * Or, it might just be a 17-character password (maybe UTF-8) * Check it for non-printable characters. The odds of ALL * of the characters being 32..255 is (1-7/8)^17, or (1/8)^17, * or 1/(2^51), which is pretty much zero. */ if (vp->length == 17) { for (i = 0; i < 17; i++) { if (vp->vp_octets[i] < 32) { already_hex = 1; break; } } } /* * Allow the user to specify ASCII or hex CHAP-Password */ if (!already_hex) { uint8_t *p; size_t len, len2; len = len2 = vp->length; if (len2 < 17) len2 = 17; p = talloc_zero_array(vp, uint8_t, len2); memcpy(p, vp->vp_strvalue, len); rad_chap_encode(request->packet, p, fr_rand() & 0xff, vp); vp->vp_octets = p; vp->length = 17; } } break; case PW_DIGEST_REALM: case PW_DIGEST_NONCE: case PW_DIGEST_METHOD: case PW_DIGEST_URI: case PW_DIGEST_QOP: case PW_DIGEST_ALGORITHM: case PW_DIGEST_BODY_DIGEST: case PW_DIGEST_CNONCE: case PW_DIGEST_NONCE_COUNT: case PW_DIGEST_USER_NAME: /* overlapping! */ { DICT_ATTR const *da; uint8_t *p, *q; p = talloc_array(vp, uint8_t, vp->length + 2); memcpy(p + 2, vp->vp_octets, vp->length); p[0] = vp->da->attr - PW_DIGEST_REALM + 1; vp->length += 2; p[1] = vp->length; da = dict_attrbyvalue(PW_DIGEST_ATTRIBUTES, 0); rad_assert(da != NULL); vp->da = da; /* * Re-do pairmemsteal ourselves, * because we play games with * vp->da, and pairmemsteal goes * to GREAT lengths to sanitize * and fix and change and * double-check the various * fields. */ memcpy(&q, &vp->vp_octets, sizeof(q)); talloc_free(q); vp->vp_octets = talloc_steal(vp, p); vp->type = VT_DATA; VERIFY_VP(vp); } break; } } /* loop over the VP's we read in */ #endif if (debug_flag) { for (vp = fr_cursor_init(&cursor, &request->packet->vps); vp; vp = fr_cursor_next(&cursor)) { /* * Take this opportunity to verify all the VALUE_PAIRs are still valid. */ if (!talloc_get_type(vp, VALUE_PAIR)) { ERROR("Expected VALUE_PAIR pointer got \"%s\"", talloc_get_name(vp)); fr_log_talloc_report(vp); rad_assert(0); } vp_print(fr_log_fp, vp); } fflush(fr_log_fp); } /* * FIXME: set IPs, etc. */ request->packet->code = PW_CODE_ACCESS_REQUEST; request->packet->src_ipaddr.af = AF_INET; request->packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK); request->packet->src_port = 18120; request->packet->dst_ipaddr.af = AF_INET; request->packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_LOOPBACK); request->packet->dst_port = 1812; /* * Build the reply template from the request. */ request->reply->sockfd = request->packet->sockfd; request->reply->dst_ipaddr = request->packet->src_ipaddr; request->reply->src_ipaddr = request->packet->dst_ipaddr; request->reply->dst_port = request->packet->src_port; request->reply->src_port = request->packet->dst_port; request->reply->id = request->packet->id; request->reply->code = 0; /* UNKNOWN code */ memcpy(request->reply->vector, request->packet->vector, sizeof(request->reply->vector)); request->reply->vps = NULL; request->reply->data = NULL; request->reply->data_len = 0; /* * Debugging */ request->log.lvl = debug_flag; request->log.func = vradlog_request; request->username = pairfind(request->packet->vps, PW_USER_NAME, 0, TAG_ANY); request->password = pairfind(request->packet->vps, PW_USER_PASSWORD, 0, TAG_ANY); return request; }
/** Write a single detail entry to file pointer * * @param[in] out Where to write entry. * @param[in] inst Instance of rlm_detail. * @param[in] request The current request. * @param[in] packet associated with the request (request, reply, proxy-request, proxy-reply...). * @param[in] compat Write out entry in compatibility mode. */ static int detail_write(FILE *out, detail_instance_t *inst, REQUEST *request, RADIUS_PACKET *packet, bool compat) { VALUE_PAIR *vp; char timestamp[256]; if (radius_xlat(timestamp, sizeof(timestamp), request, inst->header, NULL, NULL) < 0) { return -1; } #define WRITE(fmt, ...) do {\ if (fprintf(out, fmt, ## __VA_ARGS__) < 0) {\ RERROR("Failed writing to detail file: %s", fr_syserror(errno));\ return -1;\ }\ } while(0) WRITE("%s\n", timestamp); /* * Write the information to the file. */ if (!compat) { /* * Print out names, if they're OK. * Numbers, if not. */ if (is_radius_code(packet->code)) { WRITE("\tPacket-Type = %s\n", fr_packet_codes[packet->code]); } else { WRITE("\tPacket-Type = %d\n", packet->code); } } if (inst->log_srcdst) { VALUE_PAIR src_vp, dst_vp; memset(&src_vp, 0, sizeof(src_vp)); memset(&dst_vp, 0, sizeof(dst_vp)); switch (packet->src_ipaddr.af) { case AF_INET: src_vp.da = dict_attrbyvalue(PW_PACKET_SRC_IP_ADDRESS, 0); src_vp.vp_ipaddr = packet->src_ipaddr.ipaddr.ip4addr.s_addr; dst_vp.da = dict_attrbyvalue(PW_PACKET_DST_IP_ADDRESS, 0); dst_vp.vp_ipaddr = packet->dst_ipaddr.ipaddr.ip4addr.s_addr; break; case AF_INET6: src_vp.da = dict_attrbyvalue(PW_PACKET_SRC_IPV6_ADDRESS, 0); memcpy(&src_vp.vp_ipv6addr, &packet->src_ipaddr.ipaddr.ip6addr, sizeof(packet->src_ipaddr.ipaddr.ip6addr)); dst_vp.da = dict_attrbyvalue(PW_PACKET_DST_IPV6_ADDRESS, 0); memcpy(&dst_vp.vp_ipv6addr, &packet->dst_ipaddr.ipaddr.ip6addr, sizeof(packet->dst_ipaddr.ipaddr.ip6addr)); break; default: break; } detail_vp_print(request, out, &src_vp); detail_vp_print(request, out, &dst_vp); src_vp.da = dict_attrbyvalue(PW_PACKET_SRC_PORT, 0); src_vp.vp_integer = packet->src_port; dst_vp.da = dict_attrbyvalue(PW_PACKET_DST_PORT, 0); dst_vp.vp_integer = packet->dst_port; detail_vp_print(request, out, &src_vp); detail_vp_print(request, out, &dst_vp); } { vp_cursor_t cursor; /* Write each attribute/value to the log file */ for (vp = fr_cursor_init(&cursor, &packet->vps); vp; vp = fr_cursor_next(&cursor)) { FR_TOKEN op; if (inst->ht && fr_hash_table_finddata(inst->ht, vp->da)) continue; /* * Don't print passwords in old format... */ if (compat && !vp->da->vendor && (vp->da->attr == PW_USER_PASSWORD)) continue; /* * Print all of the attributes, operator should always be '='. */ op = vp->op; vp->op = T_OP_EQ; vp_print(out, vp); vp->op = op; } } /* * Add non-protocol attributes. */ if (compat) { #ifdef WITH_PROXY if (request->proxy) { char proxy_buffer[128]; inet_ntop(request->proxy->dst_ipaddr.af, &request->proxy->dst_ipaddr.ipaddr, proxy_buffer, sizeof(proxy_buffer)); WRITE("\tFreeradius-Proxied-To = %s\n", proxy_buffer); } #endif WRITE("\tTimestamp = %ld\n", (unsigned long) request->timestamp); } WRITE("\n"); return 0; }