home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / radius-2.zip / src / radpass.c < prev    next >
C/C++ Source or Header  |  1996-05-14  |  7KB  |  292 lines

  1. /*
  2.  *
  3.  *    RADIUS
  4.  *    Remote Authentication Dial In User Service
  5.  *
  6.  *
  7.  *    Livingston Enterprises, Inc.
  8.  *    6920 Koll Center Parkway
  9.  *    Pleasanton, CA   94566
  10.  *
  11.  *    Copyright 1992 Livingston Enterprises, Inc.
  12.  *
  13.  *    Permission to use, copy, modify, and distribute this software for any
  14.  *    purpose and without fee is hereby granted, provided that this
  15.  *    copyright and permission notice appear on all copies and supporting
  16.  *    documentation, the name of Livingston Enterprises, Inc. not be used
  17.  *    in advertising or publicity pertaining to distribution of the
  18.  *    program without specific prior permission, and notice be given
  19.  *    in supporting documentation that copying and distribution is by
  20.  *    permission of Livingston Enterprises, Inc.   
  21.  *
  22.  *    Livingston Enterprises, Inc. makes no representations about
  23.  *    the suitability of this software for any purpose.  It is
  24.  *    provided "as is" without express or implied warranty.
  25.  *
  26.  */
  27.  
  28. static char sccsid[] =
  29. "@(#)radpass.c    1.5 Copyright 1992 Livingston Enterprises Inc";
  30.  
  31. #include    <sys/types.h>
  32. #include    <sys/socket.h>
  33. #include    <netinet/in.h>
  34.  
  35. #include    <stdio.h>
  36. #include    <unistd.h>
  37. #include    <netdb.h>
  38. #include    <pwd.h>
  39.  
  40. #include    "radius.h"
  41.  
  42. #define MAXPWNAM    8
  43. #define MAXPASS        16
  44.  
  45. u_char        recv_buffer[4096];
  46. u_char        send_buffer[4096];
  47. u_char        *progname;
  48. int        sockfd;
  49. u_char        vector[AUTH_VECTOR_LEN];
  50. u_char        oldpass[AUTH_PASS_LEN];
  51.  
  52. main(argc, argv)
  53. int    argc;
  54. u_char    *argv[];
  55. {
  56.     int            salen;
  57.     int            result;
  58.     struct    sockaddr    salocal;
  59.     struct    sockaddr    saremote;
  60.     struct    sockaddr_in    *sin;
  61.     struct    servent        *svp;
  62.         u_short                 svc_port;
  63.     AUTH_HDR        *auth;
  64.     u_char            *username;
  65.     u_char            newpass1[AUTH_PASS_LEN];
  66.     u_char            newpass2[AUTH_PASS_LEN];
  67.     u_char            passbuf[AUTH_PASS_LEN];
  68.     u_char            md5buf[256];
  69.     u_char            *oldvector;
  70.     UINT4            get_ipaddr();
  71.     UINT4            auth_ipaddr;
  72.     u_short            local_port;
  73.     int            total_length;
  74.     u_char            *ptr;
  75.     int            length;
  76.     int            secretlen;
  77.     int            i;
  78.     char            *getpass();
  79.  
  80.     progname = argv[0];
  81.  
  82.     if(argc != 2) {
  83.         usage();
  84.     }
  85.     /* Get the user name */
  86.     username = argv[1];
  87.  
  88.     svc_port = 1645;
  89.  
  90.     /* Get the IP address of the authentication server */
  91.     if((auth_ipaddr = get_ipaddr("radius-server")) == (UINT4)0) {
  92.         fprintf(stderr, "Couldn't find host radius-server\n");
  93.         exit(-1);
  94.     }
  95.  
  96.     sockfd = socket (AF_INET, SOCK_DGRAM, 0);
  97.     if (sockfd < 0) {
  98.         (void) perror ("socket");
  99.         exit(-1);
  100.     }
  101.  
  102.     sin = (struct sockaddr_in *) & salocal;
  103.         memset ((char *) sin, '\0', sizeof (salocal));
  104.     sin->sin_family = AF_INET;
  105.     sin->sin_addr.s_addr = INADDR_ANY;
  106.  
  107.     local_port = 1025;
  108.     do {
  109.         local_port++;
  110.         sin->sin_port = htons((u_short)local_port);
  111.     } while((bind(sockfd, &salocal, sizeof (struct sockaddr_in)) < 0) &&
  112.                         local_port < 64000);
  113.     if(local_port >= 64000) {
  114.         close(sockfd);
  115.         (void) perror ("bind");
  116.         exit(-1);
  117.     }
  118.  
  119.     printf("Changing Password for user %s\n", username);
  120.  
  121.     /* Get their old password */
  122.     strcpy((char *)oldpass, getpass("Old Password:"));
  123.     if(*oldpass == '\0') {
  124.         exit(0);
  125.     }
  126.  
  127.     /* Get their new password */
  128.     strcpy((char *)newpass1, getpass("New Password:"));
  129.     if(*newpass1 == '\0') {
  130.         exit(0);
  131.     }
  132.  
  133.     /* Get their new password again */
  134.     strcpy((char *)newpass2, getpass("Re-type New Password:"));
  135.     if(strcmp(newpass1, newpass2) != 0) {
  136.         printf("New Passwords didn't match\n");
  137.         exit(-1);
  138.     }
  139.  
  140.     /* Build a password change request */
  141.     auth = (AUTH_HDR *)send_buffer;
  142.     auth->code = PW_PASSWORD_REQUEST;
  143.     auth->id = 0;
  144.     random_vector(vector);
  145.     memcpy(auth->vector, vector, AUTH_VECTOR_LEN);
  146.     total_length = AUTH_HDR_LEN;
  147.     ptr = auth->data;
  148.  
  149.     /* User Name */
  150.     *ptr++ = PW_USER_NAME;
  151.     length = strlen(username);
  152.     if(length > MAXPWNAM) {
  153.         length = MAXPWNAM;
  154.     }
  155.     *ptr++ = length + 2;
  156.     memcpy(ptr, username, length);
  157.     ptr += length;
  158.     total_length += length + 2;
  159.  
  160.     /* New Password */
  161.     *ptr++ = PW_PASSWORD;
  162.     *ptr++ = AUTH_PASS_LEN + 2;
  163.  
  164.     /* Encrypt the Password */
  165.     length = strlen(newpass1);
  166.     if(length > MAXPASS) {
  167.         length = MAXPASS;
  168.     }
  169.     memset(passbuf, 0, AUTH_PASS_LEN);
  170.     memcpy(passbuf, newpass1, length);
  171.     /* Calculate the MD5 Digest */
  172.     secretlen = strlen(oldpass);
  173.     strcpy(md5buf, oldpass);
  174.     memcpy(md5buf + secretlen, auth->vector, AUTH_VECTOR_LEN);
  175.     md5_calc(ptr, md5buf, secretlen + AUTH_VECTOR_LEN);
  176.     oldvector = ptr;
  177.     /* Xor the password into the MD5 digest */
  178.     for(i = 0;i < AUTH_PASS_LEN;i++) {
  179.         *ptr++ ^= passbuf[i];
  180.     }
  181.     total_length += AUTH_PASS_LEN + 2;
  182.  
  183.     /* Old Password */
  184.     *ptr++ = PW_OLD_PASSWORD;
  185.     *ptr++ = AUTH_PASS_LEN + 2;
  186.  
  187.     /* Encrypt the Password */
  188.     length = strlen(oldpass);
  189.     if(length > MAXPASS) {
  190.         length = MAXPASS;
  191.     }
  192.     memset(passbuf, 0, AUTH_PASS_LEN);
  193.     memcpy(passbuf, oldpass, length);
  194.     /* Calculate the MD5 Digest */
  195.     secretlen = strlen(oldpass);
  196.     strcpy(md5buf, oldpass);
  197.     memcpy(md5buf + secretlen, oldvector, AUTH_VECTOR_LEN);
  198.     md5_calc(ptr, md5buf, secretlen + AUTH_VECTOR_LEN);
  199.  
  200.     /* Xor the password into the MD5 digest */
  201.     for(i = 0;i < AUTH_PASS_LEN;i++) {
  202.         *ptr++ ^= passbuf[i];
  203.     }
  204.     total_length += AUTH_PASS_LEN + 2;
  205.  
  206.     auth->length = htonl(total_length);
  207.  
  208.     sin = (struct sockaddr_in *) & saremote;
  209.         memset ((char *) sin, '\0', sizeof (saremote));
  210.     sin->sin_family = AF_INET;
  211.     sin->sin_addr.s_addr = htonl(auth_ipaddr);
  212.     sin->sin_port = htons(svc_port);
  213.  
  214.     sendto(sockfd, (char *)auth, (int)total_length, (int)0,
  215.             &saremote, sizeof(struct sockaddr_in));
  216.  
  217.     salen = sizeof (saremote);
  218.     result = recvfrom (sockfd, (char *) recv_buffer,
  219.             (int) sizeof(recv_buffer),
  220.             (int) 0, & saremote, & salen);
  221.  
  222.     if(result > 0) {
  223.         result_recv(sin->sin_addr.s_addr,
  224.                     sin->sin_port, recv_buffer, result);
  225.         exit(0);
  226.     }
  227.     (void) perror ("recv");
  228.     close(sockfd);
  229.     exit(0);
  230. }
  231.  
  232. result_recv(host, udp_port, buffer, length)
  233. UINT4    host;
  234. u_short    udp_port;
  235. u_char    *buffer;
  236. int    length;
  237. {
  238.     AUTH_HDR    *auth;
  239.     int        totallen;
  240.     char        *ip_hostname();
  241.     u_char        reply_digest[AUTH_VECTOR_LEN];
  242.     u_char        calc_digest[AUTH_VECTOR_LEN];
  243.     int        secretlen;
  244.  
  245.     auth = (AUTH_HDR *)buffer;
  246.     totallen = ntohs(auth->length);
  247.  
  248.     if(totallen != AUTH_HDR_LEN) {
  249.         printf("Received invalid reply length from server\n");
  250.         exit(-1);
  251.     }
  252.  
  253.     /* Verify the reply digest */
  254.     memcpy(reply_digest, auth->vector, AUTH_VECTOR_LEN);
  255.     memcpy(auth->vector, vector, AUTH_VECTOR_LEN);
  256.     secretlen = strlen(oldpass);
  257.     memcpy(buffer + AUTH_HDR_LEN, oldpass, secretlen);
  258.     md5_calc(calc_digest, (char *)auth, AUTH_HDR_LEN);
  259.  
  260.     if(memcmp(reply_digest, calc_digest, AUTH_VECTOR_LEN) != 0) {
  261.         printf("Warning: Received invalid reply digest from server\n");
  262.     }
  263.  
  264.     if(auth->code == PW_PASSWORD_ACK) {
  265.         printf("Password successfully changed\n");
  266.     }
  267.     else {
  268.         printf("Request Denied\n");
  269.     }
  270. }
  271.  
  272. usage()
  273. {
  274.     printf("Usage: %s username\n", progname);
  275.     exit(-1);
  276. }
  277.  
  278. random_vector(vector)
  279. u_char    *vector;
  280. {
  281.     int    randno;
  282.     int    i;
  283.  
  284.     srand(time(0));
  285.     for(i = 0;i < AUTH_VECTOR_LEN;) {
  286.         randno = rand();
  287.         memcpy(vector, &randno, sizeof(int));
  288.         vector += sizeof(int);
  289.         i += sizeof(int);
  290.     }
  291. }
  292.