diff -Naur radiusd-cistron-1.6.2-stable/Solaris/radiusd.init radiusd-cistron-1.6.2-stable-PAM/Solaris/radiusd.init --- radiusd-cistron-1.6.2-stable/Solaris/radiusd.init Thu Jan 1 01:00:00 1970 +++ radiusd-cistron-1.6.2-stable-PAM/Solaris/radiusd.init Thu Feb 24 15:53:17 2000 @@ -0,0 +1,27 @@ +#!/bin/sh +# + + + +case "$1" in +'start') + echo "Cistron radius server starting." + /usr/local/sbin/radiusd -y 1>/dev/console + ;; +'stop') + [ ! -f /var/run/radiusd.pid ] && exit 0 + syspid=`cat /var/run/radiusd.pid` + if [ "$syspid" -gt 0 ]; then + echo "Stopping the radius server." + kill $syspid 2>&1 | /usr/bin/grep -v "no such process" + fi + ;; +'restart') + $0 stop + $0 start + ;; +*) + echo "Usage: /etc/init.d/radiusd { start | stop }" + ;; +esac +exit 0 diff -Naur radiusd-cistron-1.6.2-stable/src/Make.inc radiusd-cistron-1.6.2-stable-PAM/src/Make.inc --- radiusd-cistron-1.6.2-stable/src/Make.inc Sun Sep 19 00:10:41 1999 +++ radiusd-cistron-1.6.2-stable-PAM/src/Make.inc Thu Feb 24 16:18:03 2000 @@ -15,7 +15,7 @@ exec.c auth.c timestr.c cache.c INCLUDES = radius.h conf.h -all: radiusd radwho radzap raduse radtest +all: radiusd radwho radzap raduse radtest authtest accttest dbm: radiusd.dbm builddbm @@ -33,7 +33,7 @@ $(CC) $(CFLAGS) $(DBM) -c radiusd.c -o radiusddbm.o acct.o: acct.c $(INCLUDES) - $(CC) $(CFLAGS) -c acct.c + $(CC) $(CFLAGS) $(PAM) -c acct.c attrprint.o: attrprint.c $(INCLUDES) $(CC) $(CFLAGS) -c attrprint.c @@ -81,6 +81,20 @@ radtest.o: radtest.c $(INCLUDES) $(CC) $(CFLAGS) -c radtest.c +authtest: authtest.o md5.o util.o dict.o attrprint.o log.o + $(CC) $(LDFLAGS) -o authtest authtest.o md5.o util.o \ + dict.o attrprint.o log.o $(LIBS) + +accttest: accttest.o md5.o util.o dict.o attrprint.o log.o + $(CC) $(LDFLAGS) -o accttest accttest.o md5.o util.o \ + dict.o attrprint.o log.o $(LIBS) + +authtest.o: authtest.c $(INCLUDES) + $(CC) $(CFLAGS) -c authtest.c + +accttest.o: accttest.c $(INCLUDES) + $(CC) $(CFLAGS) -c accttest.c + md5.o: md5.c md5.h $(CC) $(CFLAGS) -c md5.c @@ -104,7 +118,7 @@ -lint -hbacvx -DLINT ../radpass.c ../md5.c ../util.c clean: - rm -f *.o radiusd radwho raduse radtest radzap builddbm radiusd.dbm + rm -f *.o radiusd radwho raduse radtest authtest accttest radzap builddbm radiusd.dbm rm -f ../build ../debian/substvars ../debian/files install: diff -Naur radiusd-cistron-1.6.2-stable/src/Makefile radiusd-cistron-1.6.2-stable-PAM/src/Makefile --- radiusd-cistron-1.6.2-stable/src/Makefile Sun Sep 19 00:10:41 1999 +++ radiusd-cistron-1.6.2-stable-PAM/src/Makefile Thu Feb 24 11:02:36 2000 @@ -1,29 +1,18 @@ # -# Makefile Radius Makefile for Linux (2.0.x, lib5 or libc6) +# Makefile Radius Makefile for Solaris 2.5.x # -# - -# -# Autoselect -lshadow and -lcrypt -# -ifneq ($(wildcard /usr/lib/libshadow.a),) -LSHADOW = -lshadow -endif -ifneq ($(wildcard /usr/lib/libcrypt.a),) -LCRYPT = -lcrypt -endif CC = gcc -CFLAGS = -Wall -g # -DNOSHADOW -LDFLAGS = # -s # tatic -LIBS = $(LSHADOW) +CFLAGS = -g # -DNOSHADOW +LDFLAGS = # -s #tatic +LIBS = -lsocket -lnsl +LCRYPT = -DBM = -DNDBM -DBMLIB = -ldb +DBM = #-DNDBM +DBMLIB = #-ldb -# Uncomment these if you want PAM support -#PAM = -DPAM -#PAMLIB = -lpam -ldl +PAM = -DPAM +PAMLIB = -lpam BINDIR = /usr/local/bin SBINDIR = /usr/local/sbin diff -Naur radiusd-cistron-1.6.2-stable/src/acct.c radiusd-cistron-1.6.2-stable-PAM/src/acct.c --- radiusd-cistron-1.6.2-stable/src/acct.c Tue Sep 28 14:30:07 1999 +++ radiusd-cistron-1.6.2-stable-PAM/src/acct.c Thu Feb 24 16:06:31 2000 @@ -689,10 +689,17 @@ */ int rad_accounting(AUTH_REQ *authreq, int activefd) { - int reply = 0; - int auth; - char pw_digest[16]; - + int reply = 0; + int auth; + int session_type; + char pw_digest[16]; + VALUE_PAIR *vp; + VALUE_PAIR *user_name; + VALUE_PAIR *user_check; + VALUE_PAIR *user_reply; + char *pamauth = NULL; + user_check = NULL; + user_reply = NULL; /* * See if we know this client, then check the * request authenticator. @@ -704,6 +711,55 @@ return -1; } +#ifdef PAM + if ((user_name = pairfind(authreq->request, PW_USER_NAME)) != NULL) { + if(user_find(user_name->strvalue, authreq->request, + &user_check, &user_reply)==0) + { + if ((vp = pairfind(user_check, PW_AUTHTYPE)) != NULL) + session_type = vp->lvalue; + if(session_type==PW_AUTHTYPE_PAM) + { + if ((vp = pairfind(user_check, PAM_AUTH_ATTR)) != NULL) { + pamauth = vp->strvalue; + } + pamauth = pamauth ? pamauth : PAM_DEFAULT_TYPE; + + if ((vp = pairfind(authreq->request, PW_ACCT_STATUS_TYPE)) != NULL) { + + switch (vp->lvalue) { + case PW_STATUS_START: + if (pam_start_accounting(user_name->strvalue, + authreq,pamauth) != 0) + { + log(L_INFO, "Pam_start_accounting failure"); + } + break; + case PW_STATUS_STOP: + if (pam_stop_accounting(user_name->strvalue, + authreq,pamauth) != 0) + { + log(L_INFO, "Pam_stop_accounting failure"); + } + break; + case PW_STATUS_ACCOUNTING_ON: + case PW_STATUS_ACCOUNTING_OFF: + log(L_INFO, "Status Accounting %d", vp->lvalue); + break; + default: + log(L_ERR, "unknown packet type %d", vp->lvalue); + break; + } + + } + } + } + pairfree(user_check); + pairfree(user_reply); + } +#endif + + if (log_stripped_names) { /* * rad_accounting_new strips authreq for us. If @@ -913,7 +969,7 @@ u.type = P_IDLE; write(fd, &u, sizeof(u)); - if ((wfp = fopen(RADWTMP, "a")) != NULL) { + if ((wfp = fopen(RADWTMP, "a")) != NULL) { make_wtmp(&u, &wt, PW_STATUS_STOP); fwrite(&wt, sizeof(wt), 1, wfp); fclose(wfp); @@ -922,7 +978,7 @@ } } close(fd); - + return (count < maxsimul) ? 0 : mpp; } diff -Naur radiusd-cistron-1.6.2-stable/src/accttest.c radiusd-cistron-1.6.2-stable-PAM/src/accttest.c --- radiusd-cistron-1.6.2-stable/src/accttest.c Thu Jan 1 01:00:00 1970 +++ radiusd-cistron-1.6.2-stable-PAM/src/accttest.c Thu Feb 24 16:04:24 2000 @@ -0,0 +1,557 @@ +/* + * + * RADIUS + * Remote Authentication Dial In User Service + * + * + * Livingston Enterprises, Inc. + * 6920 Koll Center Parkway + * Pleasanton, CA 94566 + * + * Copyright 1992 Livingston Enterprises, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose and without fee is hereby granted, provided that this + * copyright and permission notice appear on all copies and supporting + * documentation, the name of Livingston Enterprises, Inc. not be used + * in advertising or publicity pertaining to distribution of the + * program without specific prior permission, and notice be given + * in supporting documentation that copying and distribution is by + * permission of Livingston Enterprises, Inc. + * + * Livingston Enterprises, Inc. makes no representations about + * the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. + * + */ + +char radtest_sccsid[] = +"@(#)radpass.c 1.5 Copyright 1992 Livingston Enterprises Inc\n" +"@(#)radtest.c 1.3 Copyright 1999 Cistron Internet Services B.V."; + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "radiusd.h" +#include "conf.h" + +#define MAXPWNAM 32 +#define MAXPASS 16 + +#define TEST_VENDOR 1 +#define TEST_USR 1 + +int i_send_buffer[2048]; +int i_recv_buffer[2048]; +char *send_buffer = (char *)i_send_buffer; +char *recv_buffer = (char *)i_recv_buffer; + +char *progname; +int sockfd; +char vector[AUTH_VECTOR_LEN]; +char *secretkey; + +char *radius_dir = RADIUS_DIR; +char *radlog_dir = NULL; +int debug_flag = 0; + +/* + * Receive UDP client requests, build an authorization request + * structure, and attach attribute-value pairs contained in + * the request to the new structure. + */ +static AUTH_REQ *test_radrecv(UINT4 host, u_short udp_port, + char *buffer, int length) +{ + u_char *ptr; + AUTH_HDR *auth; + int totallen; + int attribute; + int attrlen; + DICT_ATTR *attr; + UINT4 lvalue; + VALUE_PAIR *first_pair; + VALUE_PAIR *prev; + VALUE_PAIR *pair; + AUTH_REQ *authreq; + + /* + * Pre-allocate the new request data structure + */ + + if((authreq = (AUTH_REQ *)malloc(sizeof(AUTH_REQ))) == + (AUTH_REQ *)NULL) { + fprintf(stderr, "%s: no memory\n", progname); + exit(1); + } + + auth = (AUTH_HDR *)buffer; + totallen = ntohs(auth->length); + + printf("radrecv: Reply from host %lx code=%d, id=%d, length=%d\n", + (u_long)host, auth->code, auth->id, totallen); + + /* + * Fill header fields + */ + authreq->ipaddr = host; + authreq->udp_port = udp_port; + authreq->id = auth->id; + authreq->code = auth->code; + memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN); + + /* + * Extract attribute-value pairs + */ + ptr = (u_char *)auth->data; + length -= AUTH_HDR_LEN; + first_pair = (VALUE_PAIR *)NULL; + prev = (VALUE_PAIR *)NULL; + + while(length > 0) { + + attribute = *ptr++; + attrlen = *ptr++; + if(attrlen < 2) { + length = 0; + continue; + } + attrlen -= 2; + if((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) { + printf("Received unknown attribute %d\n", attribute); + } + else if ( attrlen >= AUTH_STRING_LEN ) { + printf("attribute %d too long, %d >= %d\n", attribute, + attrlen, AUTH_STRING_LEN); + } + else { + if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) == + (VALUE_PAIR *)NULL) { + fprintf(stderr, "%s: no memory\n", + progname); + exit(1); + } + /* Same size */ + strcpy(pair->name, attr->name); + pair->attribute = attr->value; + pair->type = attr->type; + pair->next = (VALUE_PAIR *)NULL; + + switch(attr->type) { + + case PW_TYPE_STRING: + memcpy(pair->strvalue, ptr, attrlen); + pair->strvalue[attrlen] = '\0'; + pair->length = attrlen; + if(first_pair == (VALUE_PAIR *)NULL) { + first_pair = pair; + } + else { + prev->next = pair; + } + prev = pair; + break; + + case PW_TYPE_INTEGER: + case PW_TYPE_IPADDR: + memcpy(&lvalue, ptr, sizeof(UINT4)); + pair->lvalue = ntohl(lvalue); + if(first_pair == (VALUE_PAIR *)NULL) { + first_pair = pair; + } + else { + prev->next = pair; + } + prev = pair; + break; + + default: + printf(" %s (Unknown Type %d)\n", attr->name,attr->type); + free(pair); + break; + } + + } + ptr += attrlen; + length -= attrlen + 2; + } + authreq->request = first_pair; + return(authreq); +} + + +/* + * Receive and print the result of the accounting request. + */ +int result_acct_recv(UINT4 host, u_short udp_port, char *buffer, int length) +{ + AUTH_HDR *auth; + int totallen; + char reply_digest[AUTH_VECTOR_LEN]; + char calc_digest[AUTH_VECTOR_LEN]; + int secretlen; + AUTH_REQ *authreq; + VALUE_PAIR *req; + + auth = (AUTH_HDR *)buffer; + totallen = ntohs(auth->length); + + if(totallen != length) { + printf("Received invalid reply length from server (want %d/ got %d)\n", totallen, length); + exit(1); + } + + authreq = test_radrecv(host, udp_port, buffer, length); + + req = authreq->request; + + while(req) { + printf(" "); + fprint_attr_val(stdout, req); + printf("\n"); + req = req->next; + } + if(auth->code != PW_ACCOUNTING_RESPONSE ) { + printf("Access denied.\n"); + return -1; + } + return 0; +} + + + + + +/* + * Print usage message and exit. + */ +void usage(void) +{ + fprintf(stderr, "Usage: %s username servername nas_port_id framed_ip_address acct_status_type nasname [ppphint] \n", + progname); + exit(1); +} + + +/* + * Generate a random vector. + */ +static void random_vector(char *vector) +{ + int randno; + int i; + + srand(time(0)); + for(i = 0;i < AUTH_VECTOR_LEN;) { + randno = rand(); + memcpy(vector, &randno, sizeof(int)); + vector += sizeof(int); + i += sizeof(int); + } +} + + +int main(int argc, char **argv) +{ + int salen,hh=0; + int result; + struct sockaddr salocal; + struct sockaddr saremote; + struct sockaddr_in *sin; + struct servent *svp; + struct timeval tv; + fd_set readfds; + u_short svc_port; + AUTH_HDR *auth; + char *username; + char *framed_ip_addr; + char *server; + char passbuf[AUTH_PASS_LEN]; + char md5buf[256]; + char nasname[256]; + UINT4 nas_ipaddr; + UINT4 framed_ipaddr; + UINT4 auth_ipaddr; + UINT4 ui; + u_short local_port; + u_short total_length; + int portno; + int acct_status; + int acct_authen=1; + int ppphint = 0; + char *ptr; + int length; + int i,j; + int bogus_packet = 0; + + progname = argv[0]; + + if (argv[1] && strcmp(argv[1], "-b") == 0) { + argv++; + argc--; + bogus_packet = 1; + } + if (argc < 6 || argc > 8) { + usage(); + } + + username = argv[1]; + server = argv[2]; + ptr = argv[3]; + if (*ptr == 's' || *ptr == 'S') ptr++; + portno = atoi(ptr); + framed_ip_addr = argv[4]; + ptr = argv[5]; + acct_status = atoi(ptr); + + if (argc > 6) + strNcpy(nasname, argv[6], sizeof(nasname)); + else + gethostname(nasname, sizeof(nasname)); + nas_ipaddr = get_ipaddr(nasname); + + if (argc > 7) ppphint = atoi(argv[7]); + dict_init(NULL); + + + for(j=0;j<=1;j++) + { + + svp = getservbyname ("radacct", "udp"); + if (svp == (struct servent *) 0) + svc_port = PW_ACCT_UDP_PORT; + else + svc_port = ntohs((u_short) svp->s_port); + + /* Get the IP address of the accounting server */ + if((auth_ipaddr = get_ipaddr(server)) == 0) { + fprintf(stderr, "Couldn't find host %s\n", server); + exit(1); + } + + fprintf(stdout, "radius accounting server: %s\n", server); + + sockfd = socket (AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) { + perror ("socket"); + exit(1); + } + + sin = (struct sockaddr_in *) &salocal; + memset (sin, 0, sizeof (salocal)); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + + local_port = 1026; + do { + local_port++; + sin->sin_port = htons((u_short)local_port); + } while((bind(sockfd, &salocal, sizeof (struct sockaddr_in)) < 0) && + local_port < 64000); + if (local_port >= 64000) { + close(sockfd); + perror ("bind"); + exit(1); + } + + /* + * Build an accounting request + */ + + auth = (AUTH_HDR *)send_buffer; + auth->code = PW_ACCOUNTING_REQUEST; + auth->id = getpid() % 256; + random_vector(vector); + memcpy(auth->vector, vector, AUTH_VECTOR_LEN); + total_length = AUTH_HDR_LEN; + ptr = auth->data; + + + /* + * User Name + */ + *ptr++ = PW_USER_NAME; + length = strlen(username); + if(length > MAXPWNAM) { + length = MAXPWNAM; + } + *ptr++ = length + 2; + memcpy(ptr, username, length); + ptr += length; + total_length += length + 2; + + + /* + *nas-port + */ + *ptr++ = PW_NAS_PORT_ID; + *ptr++ = 6; + ui = htonl(portno); + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + total_length += 6; + + /* + *ip client + */ + framed_ipaddr=ipstr2long(framed_ip_addr); + *ptr++ = PW_FRAMED_IP_ADDRESS; + *ptr++ = 6; + ui = htonl(framed_ipaddr); + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + total_length += 6; + *ptr++ = PW_ACCT_STATUS_TYPE; + *ptr++ = 6; + ui = htonl(acct_status); + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + total_length += 6; + + + *ptr++ = PW_ACCT_AUTHENTIC; + *ptr++ = 6; + ui = htonl(acct_authen); + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + total_length += 6; + + *ptr++ = PW_ACCT_SESSION_ID; + length = strlen("124"); + if(length > MAXPWNAM) { + length = MAXPWNAM; + } + *ptr++ = length + 2; + memcpy(ptr, "123", length); + ptr += length; + total_length += length + 2; +#if TEST_VENDOR + *ptr++ = PW_VENDOR_SPECIFIC; + *ptr++ = 18; + ui = htonl(307); /* livingston */ + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + + *ptr++ = 2; /* LE-Terminate-Detail */ + *ptr++ = 6; /* len */ + strcpy(ptr, "test"); + ptr += 4; + + *ptr++ = 3; /* LE-Advice-of-Charge */ + *ptr++ = 6; /* len */ + strcpy(ptr, "TiNC"); + ptr += 4; + + total_length += 18; +#endif + +#if TEST_USR + *ptr++ = PW_VENDOR_SPECIFIC; + *ptr++ = 14; + ui = htonl(429); /* USR */ + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + ui = htonl(0x9823); /* Terminal-Type */ + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + strcpy(ptr, "test"); + ptr += 4; + total_length += 14; +#endif + + + *ptr++ = PW_NAS_IP_ADDRESS; + *ptr++ = 6; + ui = htonl(nas_ipaddr); + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + total_length += 6; + + /* + * We might need to add a PPP hint. + */ + if (ppphint) { + *ptr++ = PW_FRAMED_PROTOCOL; + *ptr++ = 6; + ui = htonl(PW_PPP); + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + total_length += 6; + } + + if (bogus_packet) { + *ptr++ = PW_FILTER_ID; + length = 4096; + *ptr++ = length + 2; + for(i = 0; i < 4096; i++) + *ptr++ = 'A'; + ptr += length; + total_length += length + 2; + } + + auth->length = htons(total_length); + + /* + * Send the request we've built. + */ + sin = (struct sockaddr_in *) &saremote; + memset (sin, 0, sizeof (saremote)); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(auth_ipaddr); + sin->sin_port = htons(svc_port); + + printf("Sending accounting request for user: %s \n", username); + for (i = 0; i < 10; i++) { + if (i > 0) printf("Re-sending request.\n"); + sendto(sockfd, (char *)auth, total_length, 0, + &saremote, sizeof(struct sockaddr_in)); + + tv.tv_sec = 3; + tv.tv_usec = 0; + FD_ZERO(&readfds); + FD_SET(sockfd, &readfds); + if (select(sockfd + 1, &readfds, NULL, NULL, &tv) == 0) + continue; + salen = sizeof (saremote); + result = recvfrom (sockfd, recv_buffer, sizeof(i_recv_buffer), + 0, &saremote, &salen); + if (result >= 0) + break; + sleep(tv.tv_sec); + } + if (result > 0 && i < 10) { + if(result_acct_recv(sin->sin_addr.s_addr, + sin->sin_port, recv_buffer, result)!=0) + exit(1); + } + else + { + close(sockfd); + printf("acounting service failure \n"); + exit(1); + } + + + if(acct_status==1) + { + printf("accounting started....\n"); + sleep(12); + close(sockfd); + acct_status++; + } + else + break; + + } + close(sockfd); + exit(0); +} diff -Naur radiusd-cistron-1.6.2-stable/src/auth.c radiusd-cistron-1.6.2-stable-PAM/src/auth.c --- radiusd-cistron-1.6.2-stable/src/auth.c Tue Nov 16 10:34:52 1999 +++ radiusd-cistron-1.6.2-stable-PAM/src/auth.c Thu Feb 24 14:56:13 2000 @@ -384,7 +384,7 @@ * pam_pass with the extra info. */ pamauth = pamauth ? pamauth : PAM_DEFAULT_TYPE; - if (pam_pass(name, string, pamauth) != 0) + if (pam_pass(name, string, authreq,pamauth) != 0) result = -1; #else log(L_ERR, "%s: PAM authentication not available", diff -Naur radiusd-cistron-1.6.2-stable/src/authtest.c radiusd-cistron-1.6.2-stable-PAM/src/authtest.c --- radiusd-cistron-1.6.2-stable/src/authtest.c Thu Jan 1 01:00:00 1970 +++ radiusd-cistron-1.6.2-stable-PAM/src/authtest.c Thu Feb 24 16:04:01 2000 @@ -0,0 +1,627 @@ +/* + * + * RADIUS + * Remote Authentication Dial In User Service + * + * + * Livingston Enterprises, Inc. + * 6920 Koll Center Parkway + * Pleasanton, CA 94566 + * + * Copyright 1992 Livingston Enterprises, Inc. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose and without fee is hereby granted, provided that this + * copyright and permission notice appear on all copies and supporting + * documentation, the name of Livingston Enterprises, Inc. not be used + * in advertising or publicity pertaining to distribution of the + * program without specific prior permission, and notice be given + * in supporting documentation that copying and distribution is by + * permission of Livingston Enterprises, Inc. + * + * Livingston Enterprises, Inc. makes no representations about + * the suitability of this software for any purpose. It is + * provided "as is" without express or implied warranty. + * + */ + +char radtest_sccsid[] = +"@(#)radpass.c 1.5 Copyright 1992 Livingston Enterprises Inc\n" +"@(#)radtest.c 1.3 Copyright 1999 Cistron Internet Services B.V."; + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "radiusd.h" +#include "conf.h" + +#define MAXPWNAM 32 +#define MAXPASS 16 + +#define TEST_VENDOR 1 +#define TEST_USR 1 + +int i_send_buffer[2048]; +int i_recv_buffer[2048]; +char *send_buffer = (char *)i_send_buffer; +char *recv_buffer = (char *)i_recv_buffer; + +char *progname; +int sockfd; +char vector[AUTH_VECTOR_LEN]; +char *secretkey; + +char *radius_dir = RADIUS_DIR; +char *radlog_dir = NULL; +int debug_flag = 0; + +/* + * Receive UDP client requests, build an authorization request + * structure, and attach attribute-value pairs contained in + * the request to the new structure. + */ +static AUTH_REQ *test_radrecv(UINT4 host, u_short udp_port, + char *buffer, int length) +{ + u_char *ptr; + AUTH_HDR *auth; + int totallen; + int attribute; + int attrlen; + DICT_ATTR *attr; + UINT4 lvalue; + VALUE_PAIR *first_pair; + VALUE_PAIR *prev; + VALUE_PAIR *pair; + AUTH_REQ *authreq; + + /* + * Pre-allocate the new request data structure + */ + + if((authreq = (AUTH_REQ *)malloc(sizeof(AUTH_REQ))) == + (AUTH_REQ *)NULL) { + fprintf(stderr, "%s: no memory\n", progname); + exit(1); + } + + auth = (AUTH_HDR *)buffer; + totallen = ntohs(auth->length); + + printf("radrecv: Reply from host %lx code=%d, id=%d, length=%d\n", + (u_long)host, auth->code, auth->id, totallen); + + /* + * Fill header fields + */ + authreq->ipaddr = host; + authreq->udp_port = udp_port; + authreq->id = auth->id; + authreq->code = auth->code; + memcpy(authreq->vector, auth->vector, AUTH_VECTOR_LEN); + + /* + * Extract attribute-value pairs + */ + ptr = (u_char *)auth->data; + length -= AUTH_HDR_LEN; + first_pair = (VALUE_PAIR *)NULL; + prev = (VALUE_PAIR *)NULL; + + while(length > 0) { + + attribute = *ptr++; + attrlen = *ptr++; + if(attrlen < 2) { + length = 0; + continue; + } + attrlen -= 2; + if((attr = dict_attrget(attribute)) == (DICT_ATTR *)NULL) { + printf("Received unknown attribute %d\n", attribute); + } + else if ( attrlen >= AUTH_STRING_LEN ) { + printf("attribute %d too long, %d >= %d\n", attribute, + attrlen, AUTH_STRING_LEN); + } + else { + if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) == + (VALUE_PAIR *)NULL) { + fprintf(stderr, "%s: no memory\n", + progname); + exit(1); + } + /* Same size */ + strcpy(pair->name, attr->name); + pair->attribute = attr->value; + pair->type = attr->type; + pair->next = (VALUE_PAIR *)NULL; + + switch(attr->type) { + + case PW_TYPE_STRING: + memcpy(pair->strvalue, ptr, attrlen); + pair->strvalue[attrlen] = '\0'; + pair->length = attrlen; + if(first_pair == (VALUE_PAIR *)NULL) { + first_pair = pair; + } + else { + prev->next = pair; + } + prev = pair; + break; + + case PW_TYPE_INTEGER: + case PW_TYPE_IPADDR: + memcpy(&lvalue, ptr, sizeof(UINT4)); + pair->lvalue = ntohl(lvalue); + if(first_pair == (VALUE_PAIR *)NULL) { + first_pair = pair; + } + else { + prev->next = pair; + } + prev = pair; + break; + + default: + printf(" %s (Unknown Type %d)\n", attr->name,attr->type); + free(pair); + break; + } + + } + ptr += attrlen; + length -= attrlen + 2; + } + authreq->request = first_pair; + return(authreq); +} + + +/* + * Receive and print the result. + */ +int result_recv(UINT4 host, u_short udp_port, char *buffer, int length) +{ + AUTH_HDR *auth; + int totallen; + char reply_digest[AUTH_VECTOR_LEN]; + char calc_digest[AUTH_VECTOR_LEN]; + int secretlen; + AUTH_REQ *authreq; + VALUE_PAIR *req; + + auth = (AUTH_HDR *)buffer; + totallen = ntohs(auth->length); + + if(totallen != length) { + printf("Received invalid reply length from server (want %d/ got %d)\n", totallen, length); + exit(1); + } + + /* Verify the reply digest */ + memcpy(reply_digest, auth->vector, AUTH_VECTOR_LEN); + memcpy(auth->vector, vector, AUTH_VECTOR_LEN); + secretlen = strlen(secretkey); + memcpy(buffer + length, secretkey, secretlen); + md5_calc(calc_digest, (char *)auth, length + secretlen); + + if(memcmp(reply_digest, calc_digest, AUTH_VECTOR_LEN) != 0) { + printf("Warning: Received invalid reply digest from server\n"); + } + + authreq = test_radrecv(host, udp_port, buffer, length); + + req = authreq->request; + + while(req) { + printf(" "); + fprint_attr_val(stdout, req); + printf("\n"); + req = req->next; + } + if(auth->code != PW_AUTHENTICATION_ACK) { + printf("Access denied.\n"); + return -1; + } + return 0; +} + +/* + * Receive and print the result of the accounting request. + */ +int result_acct_recv(UINT4 host, u_short udp_port, char *buffer, int length) +{ + AUTH_HDR *auth; + int totallen; + char reply_digest[AUTH_VECTOR_LEN]; + char calc_digest[AUTH_VECTOR_LEN]; + int secretlen; + AUTH_REQ *authreq; + VALUE_PAIR *req; + + auth = (AUTH_HDR *)buffer; + totallen = ntohs(auth->length); + + if(totallen != length) { + printf("Received invalid reply length from server (want %d/ got %d)\n", totallen, length); + exit(1); + } + + /* Verify the reply digest */ + memcpy(reply_digest, auth->vector, AUTH_VECTOR_LEN); + memcpy(auth->vector, vector, AUTH_VECTOR_LEN); + secretlen = strlen(secretkey); + memcpy(buffer + length, secretkey, secretlen); + md5_calc(calc_digest, (char *)auth, length + secretlen); + + if(memcmp(reply_digest, calc_digest, AUTH_VECTOR_LEN) != 0) { + printf("Warning: Received invalid reply digest from server\n"); + } + + authreq = test_radrecv(host, udp_port, buffer, length); + + req = authreq->request; + + while(req) { + printf(" "); + fprint_attr_val(stdout, req); + printf("\n"); + req = req->next; + } + if(auth->code != PW_ACCOUNTING_RESPONSE ) { + printf("Access denied.\n"); + return -1; + } + return 0; +} + + + + + +/* + * Print usage message and exit. + */ +void usage(void) +{ + fprintf(stderr, "Usage: %s username passwd servername nas_port_id secretkey cli called-station-id framed-ip-address [ppphint] [nasname]\n", + progname); + exit(1); +} + + +/* + * Generate a random vector. + */ +static void random_vector(char *vector) +{ + int randno; + int i; + + srand(time(0)); + for(i = 0;i < AUTH_VECTOR_LEN;) { + randno = rand(); + memcpy(vector, &randno, sizeof(int)); + vector += sizeof(int); + i += sizeof(int); + } +} + + +int main(int argc, char **argv) +{ + int salen,hh=0; + int result; + struct sockaddr salocal; + struct sockaddr saremote; + struct sockaddr_in *sin; + struct servent *svp; + struct timeval tv; + fd_set readfds; + u_short svc_port; + AUTH_HDR *auth; + char *username; + char *cli; + char *called; + char *framed_ip_addr; + char *passwd; + char *server; + char passbuf[AUTH_PASS_LEN]; + char md5buf[256]; + char nasname[256]; + UINT4 nas_ipaddr; + UINT4 framed_ipaddr; + UINT4 auth_ipaddr; + UINT4 ui; + u_short local_port; + u_short total_length; + int portno; + int ppphint = 0; + char *ptr; + int length; + int secretlen; + int i,j; + int bogus_packet = 0; + + progname = argv[0]; + + if (argv[1] && strcmp(argv[1], "-b") == 0) { + argv++; + argc--; + bogus_packet = 1; + } + + if (argc < 9 || argc > 11) { + usage(); + } + username = argv[1]; + passwd = argv[2]; + server = argv[3]; + secretkey = argv[5]; + cli = argv[6]; + called = argv[7]; + framed_ip_addr = argv[8]; + ptr = argv[4]; + if (*ptr == 's' || *ptr == 'S') ptr++; + portno = atoi(ptr); + if (argc > 9) ppphint = atoi(argv[9]); + + if (argc > 10) + strncpy(nasname, argv[10], sizeof(nasname)); + else + gethostname(nasname, sizeof(nasname)); + nas_ipaddr = get_ipaddr(nasname); + + dict_init(NULL); + + /* + * Open a connection to the server. + */ + svp = getservbyname ("radius", "udp"); + if (svp == (struct servent *) 0) + svc_port = PW_AUTH_UDP_PORT; + else + svc_port = ntohs((u_short) svp->s_port); + + /* Get the IP address of the authentication server */ + if((auth_ipaddr = get_ipaddr(server)) == 0) { + fprintf(stderr, "Couldn't find host %s\n", server); + exit(1); + } + + fprintf(stdout, "radius authentication server: %s \n", server); + /*framed_ipaddr = get_ipaddr(framed_ip_addr);*/ + + sockfd = socket (AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) { + perror ("socket"); + exit(1); + } + + sin = (struct sockaddr_in *) &salocal; + memset (sin, 0, sizeof (salocal)); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = INADDR_ANY; + + local_port = 1025; + do { + local_port++; + sin->sin_port = htons((u_short)local_port); + } while((bind(sockfd, &salocal, sizeof (struct sockaddr_in)) < 0) && + local_port < 64000); + if (local_port >= 64000) { + close(sockfd); + perror ("bind"); + exit(1); + } + + /* + * Build an authentication request + */ + + auth = (AUTH_HDR *)send_buffer; + auth->code = PW_AUTHENTICATION_REQUEST; + auth->id = getpid() % 256; + random_vector(vector); + memcpy(auth->vector, vector, AUTH_VECTOR_LEN); + total_length = AUTH_HDR_LEN; + ptr = auth->data; + + /* + *cli + */ + *ptr++ = PW_CALLING_STATION_ID; + length = strlen(cli); + if(length > 16) { + length = 16; + } + *ptr++ = length + 2; + memcpy(ptr, cli, length); + ptr += length; + total_length += length + 2; +/****************/ + /* + *called-station-id + */ + *ptr++ = PW_CALLED_STATION_ID; + length = strlen(called); + if(length > 16) { + length = 16; + } + *ptr++ = length + 2; + memcpy(ptr, called, length); + ptr += length; + total_length += length + 2; + /* + *ip client + */ + framed_ipaddr=ipstr2long(framed_ip_addr); + *ptr++ = PW_FRAMED_IP_ADDRESS; + *ptr++ = 6; + ui = htonl(framed_ipaddr); + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + total_length += 6; + + /* + * User Name + */ + *ptr++ = PW_USER_NAME; + length = strlen(username); + if(length > MAXPWNAM) { + length = MAXPWNAM; + } + *ptr++ = length + 2; + memcpy(ptr, username, length); + ptr += length; + total_length += length + 2; + + /* + * Password + */ + *ptr++ = PW_PASSWORD; + *ptr++ = AUTH_PASS_LEN + 2; + + length = strlen(passwd); + if(length > MAXPASS) { + length = MAXPASS; + } + memset(passbuf, 0, AUTH_PASS_LEN); + memcpy(passbuf, passwd, length); + + /* Calculate the MD5 Digest */ + secretlen = strlen(secretkey); + strNcpy(md5buf, secretkey, sizeof(md5buf)); + memcpy(md5buf + secretlen, auth->vector, AUTH_VECTOR_LEN); + md5_calc(ptr, md5buf, secretlen + AUTH_VECTOR_LEN); + + /* Xor the password into the MD5 digest */ + for(i = 0;i < AUTH_PASS_LEN;i++) { + *ptr++ ^= passbuf[i]; + } + total_length += AUTH_PASS_LEN + 2; + + *ptr++ = PW_NAS_PORT_ID; + *ptr++ = 6; + ui = htonl(portno); + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + total_length += 6; + + +#if TEST_VENDOR + *ptr++ = PW_VENDOR_SPECIFIC; + *ptr++ = 18; + ui = htonl(307); /* livingston */ + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + + *ptr++ = 2; /* LE-Terminate-Detail */ + *ptr++ = 6; /* len */ + strcpy(ptr, "test"); + ptr += 4; + + *ptr++ = 3; /* LE-Advice-of-Charge */ + *ptr++ = 6; /* len */ + strcpy(ptr, "TiNC"); + ptr += 4; + + total_length += 18; +#endif + +#if TEST_USR + *ptr++ = PW_VENDOR_SPECIFIC; + *ptr++ = 14; + ui = htonl(429); /* USR */ + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + ui = htonl(0x9823); /* Terminal-Type */ + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + strcpy(ptr, "test"); + ptr += 4; + total_length += 14; +#endif + + *ptr++ = PW_NAS_IP_ADDRESS; + *ptr++ = 6; + ui = htonl(nas_ipaddr); + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + total_length += 6; + + /* + * We might need to add a PPP hint. + */ + if (ppphint) { + *ptr++ = PW_FRAMED_PROTOCOL; + *ptr++ = 6; + ui = htonl(PW_PPP); + memcpy(ptr, &ui, sizeof(UINT4)); + ptr += 4; + total_length += 6; + } + + if (bogus_packet) { + *ptr++ = PW_FILTER_ID; + length = 4096; + *ptr++ = length + 2; + for(i = 0; i < 4096; i++) + *ptr++ = 'A'; + ptr += length; + total_length += length + 2; + } + + auth->length = htons(total_length); + + /* + * Send the request we've built. + */ + sin = (struct sockaddr_in *) &saremote; + memset (sin, 0, sizeof (saremote)); + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(auth_ipaddr); + sin->sin_port = htons(svc_port); + + printf("Sending autentication request for user: %s\n", username); + for (i = 0; i < 10; i++) { + if (i > 0) printf("Re-sending request.\n"); + sendto(sockfd, (char *)auth, total_length, 0, + &saremote, sizeof(struct sockaddr_in)); + + sleep(2); + tv.tv_sec = 3; + tv.tv_usec = 0; + FD_ZERO(&readfds); + FD_SET(sockfd, &readfds); + if (select(sockfd + 1, &readfds, NULL, NULL, &tv) == 0) + continue; + salen = sizeof (saremote); + result = recvfrom (sockfd, recv_buffer, sizeof(i_recv_buffer), + 0, &saremote, &salen); + if (result >= 0) + break; + sleep(tv.tv_sec); + } + + if (result > 0 && i < 10) { + result_recv(sin->sin_addr.s_addr, + sin->sin_port, recv_buffer, result); + exit(0); + } + printf("No answer.\n"); + close(sockfd); + exit(1); +} diff -Naur radiusd-cistron-1.6.2-stable/src/pam.c radiusd-cistron-1.6.2-stable-PAM/src/pam.c --- radiusd-cistron-1.6.2-stable/src/pam.c Sun Sep 19 00:10:41 1999 +++ radiusd-cistron-1.6.2-stable-PAM/src/pam.c Thu Feb 24 16:10:04 2000 @@ -26,7 +26,6 @@ #include #include "radiusd.h" - /************************************************************************* * * Function: PAM_conv @@ -103,16 +102,52 @@ * allows you to have multiple authentication types (i.e. multiple * files associated with radius in /etc/pam.d) */ -int pam_pass(char *name, char *passwd, const char *pamauth) + +int pam_pass(char *name, char *passwd, AUTH_REQ *data, const char *pamauth) { pam_handle_t *pamh=NULL; int retval; + char ip_str[16]; + char porta[16]; + char *lpszRemoteUser=NULL; + VALUE_PAIR *framed_ip; + VALUE_PAIR *calling_id; + VALUE_PAIR *called_id; + VALUE_PAIR *nas_port; PAM_username = name; PAM_password = passwd; - DEBUG("pam_pass: using pamauth string <%s> for pam.conf lookup", pamauth); + if( (calling_id=pairfind(data->request, PW_CALLING_STATION_ID)) && (called_id=pairfind(data->request, PW_CALLED_STATION_ID))!= NULL ) + { + if( (lpszRemoteUser = calloc(strlen(name)+strlen(calling_id->strvalue)+strlen(called_id->strvalue)+3,sizeof(char)))!=NULL) + sprintf(lpszRemoteUser,"%s:%s/%s",name,calling_id->strvalue, called_id->strvalue); + } +else + { + if( (calling_id=pairfind(data->request, PW_CALLING_STATION_ID)) && (called_id=pairfind(data->request, PW_CALLED_STATION_ID))== NULL ) + { + if(( lpszRemoteUser = calloc(strlen(name)+strlen(calling_id->strvalue)+2,sizeof(char)))!=NULL) + sprintf(lpszRemoteUser,"%s:%s",name,calling_id->strvalue); + } + } + retval = pam_start(pamauth, name, &conv, &pamh); + if(lpszRemoteUser!=NULL) + { + pam_set_item(pamh,PAM_RUSER,lpszRemoteUser); + free(lpszRemoteUser); + } + if( (framed_ip=pairfind(data->request, PW_FRAMED_IP_ADDRESS)) != NULL ) + { + ipaddr2str(ip_str,framed_ip->lvalue); + pam_set_item(pamh,PAM_RHOST,ip_str); + } + if ((nas_port=pairfind(data->request, PW_NAS_PORT_ID) )!= NULL ) + { + sprintf(porta,"%lu",nas_port->lvalue); + pam_set_item(pamh,PAM_TTY,porta); + } if (retval == PAM_SUCCESS) { DEBUG("pam_pass: function pam_start succeeded for <%s>", name); retval = pam_authenticate(pamh, 0); @@ -125,12 +160,93 @@ DEBUG("pam_pass: function pam_acct_mgmt succeeded for <%s>", name); pam_end(pamh, 0); return(0); - } else { + } + DEBUG("pam_pass: PAM FAILED for <%s> failed", name); pam_end(pamh, 0); - return (-1); - } + return -1; + } +int pam_start_accounting(char *user_name, AUTH_REQ *data, const char *pamauth) +{ + pam_handle_t *pamh=NULL; + int retval; + char ip_str[16]; + char porta[16]; + VALUE_PAIR *framed_ip; + VALUE_PAIR *calling_id; + VALUE_PAIR *nas_port; + + PAM_username = user_name; + + retval = pam_start(pamauth, user_name, &conv, &pamh); + + if (retval == PAM_SUCCESS) { + if ((framed_ip=pairfind(data->request, PW_FRAMED_IP_ADDRESS) )!= NULL ) + { + ipaddr2str(ip_str,framed_ip->lvalue); + pam_set_item(pamh,PAM_RHOST,ip_str); + } + if ((nas_port=pairfind(data->request, PW_NAS_PORT_ID) )!= NULL ) + { + sprintf(porta,"%lu",nas_port->lvalue); + pam_set_item(pamh,PAM_TTY,porta); + } + DEBUG("pam_start_accounting: function pam_start succeeded for %s", user_name); + retval = pam_open_session(pamh, 0); + } + if (retval == PAM_SUCCESS) { + DEBUG("pam_start_accounting: function pam_open_session succeeded for %s", user_name); + pam_end(pamh, 0); + return (0); + } + else { + DEBUG("pam_start_accounting: PAM FAILED for <%s> failed %s",user_name, pam_strerror(pamh,retval)); + pam_end(pamh, 0); + return -1; + } + return 0; + } + +int pam_stop_accounting(char *user_name,AUTH_REQ *data, const char *pamauth) +{ + pam_handle_t *pamh=NULL; + int retval; + char ip_str[16]; + char porta[16]; + VALUE_PAIR *framed_ip; + VALUE_PAIR *calling_id; + VALUE_PAIR *nas_port; + + PAM_username = user_name; + + retval = pam_start(pamauth, user_name, &conv, &pamh); + if (retval == PAM_SUCCESS) { + DEBUG("pam_stop_accounting: function pam_start succeeded for <%s>", user_name); + if ((framed_ip=pairfind(data->request, PW_FRAMED_IP_ADDRESS) )!= NULL ) + { + ipaddr2str(ip_str,framed_ip->lvalue); + pam_set_item(pamh,PAM_RHOST,ip_str); + } + if ((nas_port=pairfind(data->request, PW_NAS_PORT_ID) )!= NULL ) + { + sprintf(porta,"%lu",nas_port->lvalue); + pam_set_item(pamh,PAM_TTY,porta); + } + retval = pam_close_session(pamh, 0); + } + if (retval == PAM_SUCCESS) { + DEBUG("pam_stop_accounting: function pam_close_session succeeded retval <%d>", retval); + pam_end(pamh, 0); + return (0); + } + else { + DEBUG("pam_stop_accounting: PAM FAILED for <%s> failed %s",user_name, pam_strerror(pamh,retval)); + pam_end(pamh, 0); + return -1; + } + return 0; + } #endif /* PAM */ diff -Naur radiusd-cistron-1.6.2-stable/src/radiusd.h radiusd-cistron-1.6.2-stable-PAM/src/radiusd.h --- radiusd-cistron-1.6.2-stable/src/radiusd.h Wed Oct 6 23:25:43 1999 +++ radiusd-cistron-1.6.2-stable-PAM/src/radiusd.h Thu Feb 24 14:57:13 2000 @@ -261,7 +261,9 @@ /* pam.c */ #ifdef PAM -int pam_pass(char *name, char *passwd, const char *pamauth); +int pam_start_accounting(char *, AUTH_REQ *, const char *); +int pam_stop_accounting(char *, AUTH_REQ *, const char *); +int pam_pass(char *name, char *passwd, AUTH_REQ *, const char *pamauth); #define PAM_DEFAULT_TYPE "radius" #endif