/** * @brief Print data as string, if possible. * * If attribute "Foo" is defined as "octets" it will normally * be printed as 0x0a0a0a. The xlat "%{string:Foo}" will instead * expand to "\n\n\n" */ static size_t xlat_string(UNUSED void *instance, REQUEST *request, const char *fmt, char *out, size_t outlen) { int len; VALUE_PAIR *vp; while (isspace((int) *fmt)) fmt++; if (outlen < 3) { nothing: *out = '\0'; return 0; } if (!radius_get_vp(request, fmt, &vp)) goto nothing; if (!vp) goto nothing; if (vp->type != PW_TYPE_OCTETS) goto nothing; len = fr_print_string(vp->vp_strvalue, vp->length, out, outlen); out[len] = '\0'; return len; }
/** Print data as string, if possible. * * If attribute "Foo" is defined as "octets" it will normally * be printed as 0x0a0a0a. The xlat "%{string:Foo}" will instead * expand to "\n\n\n" */ static ssize_t xlat_string(UNUSED void *instance, REQUEST *request, char const *fmt, char *out, size_t outlen) { size_t len; ssize_t ret; VALUE_PAIR *vp; uint8_t const *p; while (isspace((int) *fmt)) fmt++; if (*fmt == '&') fmt++; if (outlen < 3) { nothing: *out = '\0'; return 0; } if ((radius_get_vp(&vp, request, fmt) < 0) || !vp) goto nothing; ret = rad_vp2data(&p, vp); if (ret < 0) { return ret; } switch (vp->da->type) { case PW_TYPE_OCTETS: len = fr_print_string((char const *) p, vp->length, out, outlen); break; case PW_TYPE_STRING: len = strlcpy(out, vp->vp_strvalue, outlen); break; default: len = fr_print_string((char const *) p, ret, out, outlen); break; } return len; }
/* * Main program */ int main(int argc, char **argv) { CONF_SECTION *maincs, *cs; FILE *fp; struct radutmp rt; char othername[256]; char nasname[1024]; char session_id[sizeof(rt.session_id)+1]; int hideshell = 0; int showsid = 0; int rawoutput = 0; int radiusoutput = 0; /* Radius attributes */ char const *portind; int c; unsigned int portno; char buffer[2048]; char const *user = NULL; int user_cmp = 0; time_t now = 0; uint32_t nas_port = ~0; uint32_t nas_ip_address = INADDR_NONE; int zap = 0; raddb_dir = RADIUS_DIR; #ifndef NDEBUG if (fr_fault_setup(getenv("PANIC_ACTION"), argv[0]) < 0) { fr_perror("radwho"); exit(EXIT_FAILURE); } #endif talloc_set_log_stderr(); while((c = getopt(argc, argv, "d:fF:nN:sSipP:crRu:U:Z")) != EOF) switch(c) { case 'd': raddb_dir = optarg; break; case 'F': radutmp_file = optarg; break; case 'h': usage(0); break; case 'S': hideshell = 1; break; case 'n': showname = 0; break; case 'N': if (inet_pton(AF_INET, optarg, &nas_ip_address) < 0) { usage(1); } break; case 's': showname = 1; break; case 'i': showsid = 1; break; case 'p': showptype = 1; break; case 'P': nas_port = atoi(optarg); break; case 'c': showcid = 1; showname = 1; break; case 'r': rawoutput = 1; break; case 'R': radiusoutput = 1; now = time(NULL); break; case 'u': user = optarg; user_cmp = 0; break; case 'U': user = optarg; user_cmp = 1; break; case 'Z': zap = 1; break; default: usage(1); break; } /* * Mismatch between the binary and the libraries it depends on */ if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) { fr_perror("radwho"); return 1; } /* * Be safe. */ if (zap && !radiusoutput) zap = 0; /* * zap EVERYONE, but only on this nas */ if (zap && !user && (~nas_port == 0)) { /* * We need to know which NAS to zap users in. */ if (nas_ip_address == INADDR_NONE) usage(1); printf("Acct-Status-Type = Accounting-Off\n"); printf("NAS-IP-Address = %s\n", hostname(buffer, sizeof(buffer), nas_ip_address)); printf("Acct-Delay-Time = 0\n"); exit(0); /* don't bother printing anything else */ } if (radutmp_file) goto have_radutmp; /* * Initialize main_config */ memset(&main_config, 0, sizeof(main_config)); /* Read radiusd.conf */ snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", raddb_dir); maincs = cf_file_read(buffer); if (!maincs) { fprintf(stderr, "%s: Error reading or parsing radiusd.conf\n", argv[0]); exit(1); } cs = cf_section_sub_find(maincs, "modules"); if (!cs) { fprintf(stderr, "%s: No modules section found in radiusd.conf\n", argv[0]); exit(1); } /* Read the radutmp section of radiusd.conf */ cs = cf_section_sub_find_name2(cs, "radutmp", NULL); if (!cs) { fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf\n", argv[0]); exit(1); } cf_section_parse(cs, NULL, module_config); /* Assign the correct path for the radutmp file */ radutmp_file = radutmpconfig.radutmp_fn; have_radutmp: if (showname < 0) showname = 1; /* * Show the users logged in on the terminal server(s). */ if ((fp = fopen(radutmp_file, "r")) == NULL) { fprintf(stderr, "%s: Error reading %s: %s\n", progname, radutmp_file, fr_syserror(errno)); return 0; } /* * Don't print the headers if raw or RADIUS */ if (!rawoutput && !radiusoutput) { fputs(showname ? hdr1 : hdr2, stdout); fputs(eol, stdout); } /* * Read the file, printing out active entries. */ while (fread(&rt, sizeof(rt), 1, fp) == 1) { char name[sizeof(rt.login) + 1]; if (rt.type != P_LOGIN) continue; /* hide logout sessions */ /* * We don't show shell users if we are * fingerd, as we have done that above. */ if (hideshell && !strchr("PCS", rt.proto)) continue; /* * Print out sessions only for the given user. */ if (user) { /* only for a particular user */ if (((user_cmp == 0) && (strncasecmp(rt.login, user, strlen(user)) != 0)) || ((user_cmp == 1) && (strncmp(rt.login, user, strlen(user)) != 0))) { continue; } } /* * Print out only for the given NAS port. */ if (~nas_port != 0) { if (rt.nas_port != nas_port) continue; } /* * Print out only for the given NAS IP address */ if (nas_ip_address != INADDR_NONE) { if (rt.nas_address != nas_ip_address) continue; } memcpy(session_id, rt.session_id, sizeof(rt.session_id)); session_id[sizeof(rt.session_id)] = 0; if (!rawoutput && rt.nas_port > (showname ? 999 : 99999)) { portind = ">"; portno = (showname ? 999 : 99999); } else { portind = "S"; portno = rt.nas_port; } /* * Print output as RADIUS attributes */ if (radiusoutput) { memcpy(nasname, rt.login, sizeof(rt.login)); nasname[sizeof(rt.login)] = '\0'; fr_print_string(nasname, 0, buffer, sizeof(buffer)); printf("User-Name = \"%s\"\n", buffer); fr_print_string(session_id, 0, buffer, sizeof(buffer)); printf("Acct-Session-Id = \"%s\"\n", buffer); if (zap) printf("Acct-Status-Type = Stop\n"); printf("NAS-IP-Address = %s\n", hostname(buffer, sizeof(buffer), rt.nas_address)); printf("NAS-Port = %u\n", rt.nas_port); switch (rt.proto) { case 'S': printf("Service-Type = Framed-User\n"); printf("Framed-Protocol = SLIP\n"); break; case 'P': printf("Service-Type = Framed-User\n"); printf("Framed-Protocol = PPP\n"); break; default: printf("Service-type = Login-User\n"); break; } if (rt.framed_address != INADDR_NONE) { printf("Framed-IP-Address = %s\n", hostname(buffer, sizeof(buffer), rt.framed_address)); } /* * Some sanity checks on the time */ if ((rt.time <= now) && (now - rt.time) <= (86400 * 365)) { printf("Acct-Session-Time = %" PRId64 "\n", (int64_t) (now - rt.time)); } if (rt.caller_id[0] != '\0') { memcpy(nasname, rt.caller_id, sizeof(rt.caller_id)); nasname[sizeof(rt.caller_id)] = '\0'; fr_print_string(nasname, 0, buffer, sizeof(buffer)); printf("Calling-Station-Id = \"%s\"\n", buffer); } printf("\n"); /* separate entries with a blank line */ continue; } /* * Show the fill name, or not. */ memcpy(name, rt.login, sizeof(rt.login)); name[sizeof(rt.login)] = '\0'; if (showname) { if (rawoutput == 0) { printf("%-10.10s %-17.17s %-5.5s %s%-3u %-9.9s %-15.15s %-.19s%s", name, showcid ? rt.caller_id : (showsid? session_id : fullname(rt.login)), proto(rt.proto, rt.porttype), portind, portno, dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } else { printf("%s,%s,%s,%s%u,%s,%s,%s%s", name, showcid ? rt.caller_id : (showsid? session_id : fullname(rt.login)), proto(rt.proto, rt.porttype), portind, portno, dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } } else { if (rawoutput == 0) { printf("%-10.10s %s%-5u %-6.6s %-13.13s %-15.15s %-.28s%s", name, portind, portno, proto(rt.proto, rt.porttype), dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } else { printf("%s,%s%u,%s,%s,%s,%s%s", name, portind, portno, proto(rt.proto, rt.porttype), dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } } } fclose(fp); return 0; }
/* * Main program, either pmwho or fingerd. */ int main(int argc, char **argv) { CONF_SECTION *maincs, *cs; FILE *fp; struct radutmp rt; char inbuf[128]; char othername[256]; char nasname[1024]; char session_id[sizeof(rt.session_id)+1]; int fingerd = 0; int hideshell = 0; int showsid = 0; int rawoutput = 0; int radiusoutput = 0; /* Radius attributes */ char *p, *q; const char *portind; int c; unsigned int portno; char buffer[2048]; const char *user = NULL; int user_cmp = 0; time_t now = 0; uint32_t nas_port = ~0; uint32_t nas_ip_address = INADDR_NONE; int zap = 0; raddb_dir = RADIUS_DIR; while((c = getopt(argc, argv, "d:fF:nN:sSipP:crRu:U:Z")) != EOF) switch(c) { case 'd': raddb_dir = optarg; break; case 'f': fingerd++; showname = 0; break; case 'F': radutmp_file = optarg; break; case 'h': usage(0); break; case 'S': hideshell = 1; break; case 'n': showname = 0; break; case 'N': if (inet_pton(AF_INET, optarg, &nas_ip_address) < 0) { usage(1); } break; case 's': showname = 1; break; case 'i': showsid = 1; break; case 'p': showptype = 1; break; case 'P': nas_port = atoi(optarg); break; case 'c': showcid = 1; showname = 1; break; case 'r': rawoutput = 1; break; case 'R': radiusoutput = 1; now = time(NULL); break; case 'u': user = optarg; user_cmp = 0; break; case 'U': user = optarg; user_cmp = 1; break; case 'Z': zap = 1; break; default: usage(1); break; } /* * Be safe. */ if (zap && !radiusoutput) zap = 0; /* * zap EVERYONE, but only on this nas */ if (zap && !user && (~nas_port == 0)) { /* * We need to know which NAS to zap users in. */ if (nas_ip_address == INADDR_NONE) usage(1); printf("Acct-Status-Type = Accounting-Off\n"); printf("NAS-IP-Address = %s\n", hostname(buffer, sizeof(buffer), nas_ip_address)); printf("Acct-Delay-Time = 0\n"); exit(0); /* don't bother printing anything else */ } if (radutmp_file) goto have_radutmp; /* * Initialize mainconfig */ memset(&mainconfig, 0, sizeof(mainconfig)); mainconfig.radlog_dest = RADLOG_STDOUT; /* Read radiusd.conf */ snprintf(buffer, sizeof(buffer), "%.200s/radiusd.conf", raddb_dir); maincs = cf_file_read(buffer); if (!maincs) { fprintf(stderr, "%s: Error reading or parsing radiusd.conf.\n", argv[0]); exit(1); } /* Read the radutmp section of radiusd.conf */ cs = cf_section_find_name2(cf_section_sub_find(maincs, "modules"), "radutmp", NULL); if(!cs) { fprintf(stderr, "%s: No configuration information in radutmp section of radiusd.conf!\n", argv[0]); exit(1); } cf_section_parse(cs, NULL, module_config); /* Assign the correct path for the radutmp file */ radutmp_file = radutmpconfig.radutmp_fn; have_radutmp: /* * See if we are "fingerd". */ if (strstr(argv[0], "fingerd")) { fingerd++; eol = "\r\n"; if (showname < 0) showname = 0; } if (showname < 0) showname = 1; if (fingerd) { /* * Read first line of the input. */ fgets(inbuf, 128, stdin); p = inbuf; while(*p == ' ' || *p == '\t') p++; if (*p == '/' && *(p + 1)) p += 2; while(*p == ' ' || *p == '\t') p++; for(q = p; *q && *q != '\r' && *q != '\n'; q++) ; *q = 0; /* * See if we fingered a specific user. */ ffile("header"); if (*p) sys_finger(p); } /* * Show the users logged in on the terminal server(s). */ if ((fp = fopen(radutmp_file, "r")) == NULL) { fprintf(stderr, "%s: Error reading %s: %s\n", progname, radutmp_file, strerror(errno)); return 0; } /* * Don't print the headers if raw or RADIUS */ if (!rawoutput && !radiusoutput) { fputs(showname ? hdr1 : hdr2, stdout); fputs(eol, stdout); } /* * Read the file, printing out active entries. */ while (fread(&rt, sizeof(rt), 1, fp) == 1) { if (rt.type != P_LOGIN) continue; /* hide logout sessions */ /* * We don't show shell users if we are * fingerd, as we have done that above. */ if (hideshell && !strchr("PCS", rt.proto)) continue; /* * Print out sessions only for the given user. */ if (user) { /* only for a particular user */ if (((user_cmp == 0) && (strncasecmp(rt.login, user, strlen(user)) != 0)) || ((user_cmp == 1) && (strncmp(rt.login, user, strlen(user)) != 0))) { continue; } } /* * Print out only for the given NAS port. */ if (~nas_port != 0) { if (rt.nas_port != nas_port) continue; } /* * Print out only for the given NAS IP address */ if (nas_ip_address != INADDR_NONE) { if (rt.nas_address != nas_ip_address) continue; } memcpy(session_id, rt.session_id, sizeof(rt.session_id)); session_id[sizeof(rt.session_id)] = 0; if (!rawoutput && rt.nas_port > (showname ? 999 : 99999)) { portind = ">"; portno = (showname ? 999 : 99999); } else { portind = "S"; portno = rt.nas_port; } /* * Print output as RADIUS attributes */ if (radiusoutput) { memcpy(nasname, rt.login, sizeof(rt.login)); nasname[sizeof(rt.login)] = '\0'; fr_print_string(nasname, 0, buffer, sizeof(buffer)); printf("User-Name = \"%s\"\n", buffer); fr_print_string(session_id, 0, buffer, sizeof(buffer)); printf("Acct-Session-Id = \"%s\"\n", buffer); if (zap) printf("Acct-Status-Type = Stop\n"); printf("NAS-IP-Address = %s\n", hostname(buffer, sizeof(buffer), rt.nas_address)); printf("NAS-Port = %u\n", rt.nas_port); switch (rt.proto) { case 'S': printf("Service-Type = Framed-User\n"); printf("Framed-Protocol = SLIP\n"); break; case 'P': printf("Service-Type = Framed-User\n"); printf("Framed-Protocol = PPP\n"); break; default: printf("Service-type = Login-User\n"); break; } if (rt.framed_address != INADDR_NONE) { printf("Framed-IP-Address = %s\n", hostname(buffer, sizeof(buffer), rt.framed_address)); } /* * Some sanity checks on the time */ if ((rt.time <= now) && (now - rt.time) <= (86400 * 365)) { printf("Acct-Session-Time = %ld\n", now - rt.time); } if (rt.caller_id[0] != '\0') { memcpy(nasname, rt.caller_id, sizeof(rt.caller_id)); nasname[sizeof(rt.caller_id)] = '\0'; fr_print_string(nasname, 0, buffer, sizeof(buffer)); printf("Calling-Station-Id = \"%s\"\n", buffer); } printf("\n"); /* separate entries with a blank line */ continue; } /* * Show the fill name, or not. */ if (showname) { printf((rawoutput == 0? rfmt1: rfmt1r), rt.login, showcid ? rt.caller_id : (showsid? session_id : fullname(rt.login)), proto(rt.proto, rt.porttype), portind, portno, dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } else { printf((rawoutput == 0? rfmt2: rfmt2r), rt.login, portind, portno, proto(rt.proto, rt.porttype), dotime(rt.time), hostname(nasname, sizeof(nasname), rt.nas_address), hostname(othername, sizeof(othername), rt.framed_address), eol); } } fclose(fp); return 0; }
/* * Make sure user/pass are clean * and then log them */ static int rad_authlog(const char *msg, REQUEST *request, int goodpass) { int logit; const char *extra_msg = NULL; char clean_password[1024]; char clean_username[1024]; char buf[1024]; char extra[1024]; VALUE_PAIR *username = NULL; if (!request->root->log_auth) { return 0; } /* * Get the correct username based on the configured value */ if (log_stripped_names == 0) { username = pairfind(request->packet->vps, PW_USER_NAME); } else { username = request->username; } /* * Clean up the username */ if (username == NULL) { strcpy(clean_username, "<no User-Name attribute>"); } else { fr_print_string((char *)username->vp_strvalue, username->length, clean_username, sizeof(clean_username)); } /* * Clean up the password */ if (request->root->log_auth_badpass || request->root->log_auth_goodpass) { if (!request->password) { VALUE_PAIR *auth_type; auth_type = pairfind(request->config_items, PW_AUTH_TYPE); if (auth_type) { snprintf(clean_password, sizeof(clean_password), "<via Auth-Type = %s>", dict_valnamebyattr(PW_AUTH_TYPE, auth_type->vp_integer)); } else { strcpy(clean_password, "<no User-Password attribute>"); } } else if (pairfind(request->packet->vps, PW_CHAP_PASSWORD)) { strcpy(clean_password, "<CHAP-Password>"); } else { fr_print_string((char *)request->password->vp_strvalue, request->password->length, clean_password, sizeof(clean_password)); } } if (goodpass) { logit = request->root->log_auth_goodpass; extra_msg = request->root->auth_goodpass_msg; } else { logit = request->root->log_auth_badpass; extra_msg = request->root->auth_badpass_msg; } if (extra_msg) { extra[0] = ' '; radius_xlat(extra + 1, sizeof(extra) - 1, extra_msg, request, NULL); } else { *extra = '\0'; } radlog_request(L_AUTH, 0, request, "%s: [%s%s%s] (%s)%s", msg, clean_username, logit ? "/" : "", logit ? clean_password : "", auth_name(buf, sizeof(buf), request, 1), extra); return 0; }
/* * Print one value into a string. * delimitst will define if strings and dates will be delimited by '"' */ int vp_prints_value(char * out, size_t outlen, VALUE_PAIR *vp, int delimitst) { DICT_VALUE *v; char buf[1024]; const char *a = NULL; size_t len; time_t t; struct tm s_tm; out[0] = '\0'; if (!vp) return 0; switch (vp->type) { case PW_TYPE_STRING: if ((delimitst == 1) && vp->flags.has_tag) { /* Tagged attribute: print delimter and ignore tag */ buf[0] = '"'; fr_print_string(vp->vp_strvalue, vp->length, buf + 1, sizeof(buf) - 2); strcat(buf, "\""); } else if (delimitst == 1) { /* Non-tagged attribute: print delimter */ buf[0] = '"'; fr_print_string(vp->vp_strvalue, vp->length, buf + 1, sizeof(buf) - 2); strcat(buf, "\""); } else if (delimitst < 0) { /* xlat.c */ strlcpy(out, vp->vp_strvalue, outlen); return strlen(out); } else { /* Non-tagged attribute: no delimiter */ fr_print_string(vp->vp_strvalue, vp->length, buf, sizeof(buf)); } a = buf; break; case PW_TYPE_INTEGER: if ( vp->flags.has_tag ) { /* Attribute value has a tag, need to ignore it */ if ((v = dict_valbyattr(vp->attribute, (vp->vp_integer & 0xffffff))) != NULL) a = v->name; else { snprintf(buf, sizeof(buf), "%u", (vp->vp_integer & 0xffffff)); a = buf; } } else { case PW_TYPE_BYTE: case PW_TYPE_SHORT: /* Normal, non-tagged attribute */ if ((v = dict_valbyattr(vp->attribute, vp->vp_integer)) != NULL) a = v->name; else { snprintf(buf, sizeof(buf), "%u", vp->vp_integer); a = buf; } } break; case PW_TYPE_DATE: t = vp->vp_date; if (delimitst == 1) { len = strftime(buf, sizeof(buf), "\"%b %e %Y %H:%M:%S %Z\"", localtime_r(&t, &s_tm)); } else { len = strftime(buf, sizeof(buf), "%b %e %Y %H:%M:%S %Z", localtime_r(&t, &s_tm)); } if (len > 0) a = buf; break; case PW_TYPE_SIGNED: /* Damned code for 1 WiMAX attribute */ snprintf(buf, sizeof(buf), "%d", vp->vp_signed); a = buf; break; case PW_TYPE_IPADDR: a = inet_ntop(AF_INET, &(vp->vp_ipaddr), buf, sizeof(buf)); break; case PW_TYPE_ABINARY: #ifdef ASCEND_BINARY a = buf; print_abinary(vp, buf, sizeof(buf)); break; #else /* FALL THROUGH */ #endif case PW_TYPE_OCTETS: if (outlen <= (2 * (vp->length + 1))) return 0; strcpy(buf, "0x"); fr_bin2hex(vp->vp_octets, buf + 2, vp->length); a = buf; break; case PW_TYPE_IFID: a = ifid_ntoa(buf, sizeof(buf), vp->vp_octets); break; case PW_TYPE_IPV6ADDR: a = inet_ntop(AF_INET6, (const struct in6_addr *) vp->vp_strvalue, buf, sizeof(buf)); break; case PW_TYPE_IPV6PREFIX: { struct in6_addr addr; /* * Alignment issues. */ memcpy(&addr, vp->vp_strvalue + 2, sizeof(addr)); a = inet_ntop(AF_INET6, &addr, buf, sizeof(buf)); if (a) { char *p = buf + strlen(buf); snprintf(p, buf + sizeof(buf) - p - 1, "/%u", (unsigned int) vp->vp_octets[1]); } } break; case PW_TYPE_ETHERNET: snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", vp->vp_ether[0], vp->vp_ether[1], vp->vp_ether[2], vp->vp_ether[3], vp->vp_ether[4], vp->vp_ether[5]); a = buf; break; case PW_TYPE_TLV: if (outlen <= (2 * (vp->length + 1))) return 0; strcpy(buf, "0x"); fr_bin2hex(vp->vp_tlv, buf + 2, vp->length); a = buf; break; default: a = "UNKNOWN-TYPE"; break; } if (a != NULL) strlcpy(out, a, outlen); return strlen(out); }