LFUNC auth_radius(UINT4 client_port, char *username, char *passwd) { VALUE_PAIR *send, *received, *vp, *service_vp; UINT4 service, ftype, ctype; char msg[4096], *p, username_realm[256]; char name[2048], value[2048]; /* more than enough */ int result; char *default_realm, *service_str, *ftype_str; DICT_VALUE *dval; send = received = NULL; /* * Determine and fill in Service-Type */ #ifdef SCP /* determine based on the username what kind of service is requested. this allows you to use one password for all accounts, but the Merit radiusd supplies you just with the right information you need for the specified service type -lf, 03/15/96 */ switch (*username) { case 'S': service = PW_FRAMED; ftype = PW_SLIP; ctype = 0; username++; break; case 'C': service = PW_FRAMED; ftype = PW_SLIP; ctype = PW_VAN_JACOBSON_TCP_IP; username++; break; case 'P': service = PW_FRAMED; ftype = PW_PPP; ctype = 0; username++; break; default: service = PW_LOGIN; ftype = 0; ctype = 0; break; } #else service = PW_LOGIN; ftype = 0; ctype = 0; #endif if (rc_avpair_add(&send, PW_SERVICE_TYPE, &service, 0, VENDOR_NONE) == NULL) return (LFUNC) NULL; /* Fill in Framed-Protocol, if neccessary */ if (ftype != 0) { if (rc_avpair_add(&send, PW_FRAMED_PROTOCOL, &ftype, 0, VENDOR_NONE) == NULL) return (LFUNC) NULL; } /* Fill in Framed-Compression, if neccessary */ if (ctype != 0) { if (rc_avpair_add(&send, PW_FRAMED_COMPRESSION, &ctype, 0, VENDOR_NONE) == NULL) return (LFUNC) NULL; } /* * Fill in User-Name */ strncpy(username_realm, username, sizeof(username_realm)); /* Append default realm */ default_realm = rc_conf_str("default_realm"); if ((strchr(username_realm, '@') == NULL) && default_realm && ((*default_realm) != '\0')) { strncat(username_realm, "@", sizeof(username_realm)); strncat(username_realm, default_realm, sizeof(username_realm)); } if (rc_avpair_add(&send, PW_USER_NAME, username_realm, 0, VENDOR_NONE) == NULL) return (LFUNC) NULL; /* * Fill in User-Password */ if (rc_avpair_add(&send, PW_USER_PASSWORD, passwd, 0, VENDOR_NONE) == NULL) return (LFUNC) NULL; result = rc_auth(client_port, send, &received, msg, NULL); if (result == OK_RC) { /* Set up a running count of attributes saved. */ int acount[256], attr; memset(acount, 0, sizeof(acount)); rc_add_env(env, "RADIUS_USER_NAME", username); vp = received; /* map-- keep track of the attributes so that we know when to add the delimiters. Note that we can only handle attributes < 256, which is the standard anyway. */ while (vp) { strcpy(name, "RADIUS_"); if (rc_avpair_tostr(vp, name+7, sizeof(name)-7, value, sizeof(value)) < 0) { rc_avpair_free(send); rc_avpair_free(received); return (LFUNC) NULL; } /* Translate "-" => "_" and uppercase*/ for(p = name; *p; p++) { *p = toupper(*p); if (*p == '-') *p = '_'; } /* Add to the attribute count and append the var if necessary. */ if ((attr = vp->attribute) < 256) { int count; if ((count = acount[attr]++) > 0) { char buf[10]; sprintf(buf, "_%d", count); strcat(name,buf); } } if (rc_add_env(env, name, value) < 0) { rc_avpair_free(send); rc_avpair_free(received); return (LFUNC) NULL; } vp = vp->next; } service_str = "(unknown)"; ftype_str = NULL; if ((service_vp = rc_avpair_get(received, PW_SERVICE_TYPE)) != NULL) if ((dval = rc_dict_getval(service_vp->lvalue, service_vp->name)) != NULL) { service_str = dval->name; } if (service_vp && (service_vp->lvalue == PW_FRAMED) && ((vp = rc_avpair_get(received, PW_FRAMED_PROTOCOL)) != NULL)) if ((dval = rc_dict_getval(vp->lvalue, vp->name)) != NULL) { ftype_str = dval->name; } rc_log(LOG_NOTICE, "authentication OK, username %s, service %s%s%s", username, service_str,(ftype_str)?"/":"", (ftype_str)?ftype_str:""); if (msg && (*msg != '\0')) printf(SC_SERVER_REPLY, msg); else printf(SC_RADIUS_OK); rc_avpair_free(send); rc_avpair_free(received); return radius_login; } else { rc_log(LOG_NOTICE, "authentication FAILED, type RADIUS, username %s", username_realm); if (msg && (*msg != '\0')) printf(SC_SERVER_REPLY, msg); else printf(SC_RADIUS_FAILED); } rc_avpair_free(send); if (received) rc_avpair_free(received); return (LFUNC) NULL; }
int rc_avpair_tostr (VALUE_PAIR *pair, char *name, int ln, char *value, int lv) { DICT_VALUE *dval; char buffer[32]; struct in_addr inad; unsigned char *ptr; *name = *value = '\0'; if (!pair || pair->name[0] == '\0') { error("rc_avpair_tostr: pair is NULL or empty"); return (-1); } strncpy(name, pair->name, (size_t) ln); switch (pair->type) { case PW_TYPE_STRING: lv--; ptr = (unsigned char *) pair->strvalue; while (*ptr != '\0') { if (!(isprint (*ptr))) { sprintf (buffer, "\\%03o", *ptr); strncat(value, buffer, (size_t) lv); lv -= 4; if (lv < 0) break; } else { strncat(value, (char *)ptr, 1); lv--; if (lv < 0) break; } ptr++; } break; case PW_TYPE_INTEGER: dval = rc_dict_getval (pair->lvalue, pair->name); if (dval != (DICT_VALUE *) NULL) { strncpy(value, dval->name, (size_t) lv-1); } else { sprintf (buffer, "%d", pair->lvalue); strncpy(value, buffer, (size_t) lv); } break; case PW_TYPE_IPADDR: inad.s_addr = htonl(pair->lvalue); strncpy (value, inet_ntoa (inad), (size_t) lv-1); break; case PW_TYPE_DATE: strftime (buffer, sizeof (buffer), "%m/%d/%y %H:%M:%S", gmtime ((time_t *) & pair->lvalue)); strncpy(value, buffer, lv-1); break; default: error("rc_avpair_tostr: unknown attribute type %d", pair->type); return (-1); break; } return 0; }
/** Translate an av_pair into two strings * * @param rh a handle to parsed configuration. * @param pair a pointer to a VALUE_PAIR structure. * @param name the name of the pair. * @param ln the size of name. * @param value the value of the pair. * @param lv the size of value. * @return 0 on success, -1 on failure. */ int rc_avpair_tostr (rc_handle const *rh, VALUE_PAIR *pair, char *name, int ln, char *value, int lv) { DICT_VALUE *dval; char buffer[32]; struct in_addr inad; unsigned char *ptr; unsigned int pos; *name = *value = '\0'; if (!pair || pair->name[0] == '\0') { rc_log(LOG_ERR, "rc_avpair_tostr: pair is NULL or empty"); return -1; } strlcpy(name, pair->name, (size_t) ln); switch (pair->type) { case PW_TYPE_STRING: lv--; pos = 0; ptr = (unsigned char *) pair->strvalue; if (pair->attribute == PW_DIGEST_ATTRIBUTES) { pair->strvalue[*(ptr + 1)] = '\0'; ptr += 2; } while (*ptr != '\0') { if (!(isprint (*ptr))) { if (lv >= 4) { snprintf (&value[pos], lv, "\\%03o", *ptr); pos += 4; lv -= 4; } else { break; } } else { if (lv > 0) { value[pos++] = *ptr; lv--; } else { break; } } ptr++; } if (lv > 0) value[pos++] = 0; else value[pos-1] = 0; break; case PW_TYPE_INTEGER: dval = rc_dict_getval (rh, pair->lvalue, pair->name); if (dval != NULL) { strlcpy(value, dval->name, (size_t) lv); } else { snprintf(value, lv, "%ld", (long int)pair->lvalue); } break; case PW_TYPE_IPADDR: inad.s_addr = htonl(pair->lvalue); strlcpy (value, inet_ntoa (inad), (size_t) lv); break; case PW_TYPE_IPV6ADDR: if (inet_ntop(AF_INET6, pair->strvalue, value, lv) == NULL) return -1; break; case PW_TYPE_IPV6PREFIX: { uint8_t ip[16]; uint8_t txt[48]; if (pair->lvalue < 2) return -1; memset(ip, 0, sizeof(ip)); memcpy(ip, pair->strvalue+2, pair->lvalue-2); if (inet_ntop(AF_INET6, ip, txt, sizeof(txt)) == NULL) return -1; snprintf(value, lv, "%s/%u", txt, (unsigned)pair->strvalue[1]); break; } case PW_TYPE_DATE: strftime (value, lv, "%m/%d/%y %H:%M:%S", gmtime ((time_t *) & pair->lvalue)); break; default: rc_log(LOG_ERR, "rc_avpair_tostr: unknown attribute type %d", pair->type); return -1; break; } return 0; }
int main (int argc, char **argv) { int result = ERROR_RC; VALUE_PAIR *send = NULL; UINT4 client_port; int c; VALUE_PAIR *vp; DICT_VALUE *dval; char *username, *service, *fproto, *type; char *path_radiusclient_conf = RC_CONFIG_FILE; char *ttyn = NULL; rc_handle *rh; extern char *optarg; pname = (pname = strrchr(argv[0],'/'))?pname+1:argv[0]; rc_openlog(pname); while ((c = getopt(argc,argv,"f:i:hV")) > 0) { switch(c) { case 'f': path_radiusclient_conf = optarg; break; case 'i': ttyn = optarg; break; case 'V': version(); break; case 'h': usage(); break; default: exit(ERROR_RC); break; } } if ((rh = rc_read_config(path_radiusclient_conf)) == NULL) exit(ERROR_RC); if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0) exit (ERROR_RC); if (rc_read_mapfile(rh, rc_conf_str(rh, "mapfile")) != 0) exit (ERROR_RC); if (ttyn != NULL) { client_port = rc_map2id(rh, ttyn); } else { /* we take stdout here, because stdin is usually connected * to our input file */ if ((ttyn = ttyname(1)) != NULL) { client_port = rc_map2id(rh, ttyn); } else { client_port = 0; } } if ((send = rc_avpair_readin(rh, stdin))) { username = service = type = "(unknown)"; fproto = NULL; if ((vp = rc_avpair_get(send, PW_ACCT_STATUS_TYPE, 0)) != NULL) if ((dval = rc_dict_getval(rh, vp->lvalue, vp->name)) != NULL) { type = dval->name; } if ((vp = rc_avpair_get(send, PW_USER_NAME, 0)) != NULL) username = vp->strvalue; if ((vp = rc_avpair_get(send, PW_SERVICE_TYPE, 0)) != NULL) if ((dval = rc_dict_getval(rh, vp->lvalue, vp->name)) != NULL) { service = dval->name; } if (vp && (vp->lvalue == PW_FRAMED) && ((vp = rc_avpair_get(send, PW_FRAMED_PROTOCOL, 0)) != NULL)) if ((dval = rc_dict_getval(rh, vp->lvalue, vp->name)) != NULL) { fproto = dval->name; } result = rc_acct(rh, client_port, send); if (result == OK_RC) { fprintf(stderr, SC_ACCT_OK); rc_log(LOG_NOTICE, "accounting OK, type %s, username %s, service %s%s%s", type, username, service,(fproto)?"/":"", (fproto)?fproto:""); } else { fprintf(stderr, SC_ACCT_FAILED, result); rc_log(LOG_NOTICE, "accounting FAILED, type %s, username %s, service %s%s%s", type, username, service,(fproto)?"/":"", (fproto)?fproto:""); } rc_avpair_free(send); } exit (result); }