18ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
28ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * $Id: sendserver.c,v 1.1 2004/11/14 07:26:26 paulus Exp $
38ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
48ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Copyright (C) 1995,1996,1997 Lars Fenneberg
58ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
68ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Copyright 1992 Livingston Enterprises, Inc.
78ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
88ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Copyright 1992,1993, 1994,1995 The Regents of the University of Michigan
98ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * and Merit Network, Inc. All Rights Reserved
108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * See the file COPYRIGHT for the respective terms and conditions.
128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * If the file is missing contact me at lf@elemental.net
138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * and I'll send you a copy.
148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <includes.h>
188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <radiusclient.h>
198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <pathnames.h>
208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void rc_random_vector (unsigned char *);
228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic int rc_check_reply (AUTH_HDR *, int, char *, unsigned char *, unsigned char);
238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Function: rc_pack_list
268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Purpose: Packs an attribute value pair list into a buffer.
288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Returns: Number of octets packed.
308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic int rc_pack_list (VALUE_PAIR *vp, char *secret, AUTH_HDR *auth)
348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int             length, i, pc, secretlen, padded_length;
368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int             total_length = 0;
378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    UINT4           lvalue;
388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char   passbuf[MAX(AUTH_PASS_LEN, CHAP_VALUE_LENGTH)];
398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char   md5buf[256];
408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    unsigned char   *buf, *vector, *lenptr;
418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    buf = auth->data;
438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    while (vp != (VALUE_PAIR *) NULL)
458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if (vp->vendorcode != VENDOR_NONE) {
488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		*buf++ = PW_VENDOR_SPECIFIC;
498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		/* Place-holder for where to put length */
518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		lenptr = buf++;
528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		/* Insert vendor code */
548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		*buf++ = 0;
558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		*buf++ = (((unsigned int) vp->vendorcode) >> 16) & 255;
568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		*buf++ = (((unsigned int) vp->vendorcode) >> 8) & 255;
578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		*buf++ = ((unsigned int) vp->vendorcode) & 255;
588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		/* Insert vendor-type */
608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		*buf++ = vp->attribute;
618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		/* Insert value */
638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		switch(vp->type) {
648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		case PW_TYPE_STRING:
658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    length = vp->lvalue;
668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    *lenptr = length + 8;
678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    *buf++ = length+2;
688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    memcpy(buf, vp->strvalue, (size_t) length);
698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    buf += length;
708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    total_length += length+8;
718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    break;
728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		case PW_TYPE_INTEGER:
738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		case PW_TYPE_IPADDR:
748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    length = sizeof(UINT4);
758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    *lenptr = length + 8;
768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    *buf++ = length+2;
778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    lvalue = htonl(vp->lvalue);
788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    memcpy(buf, (char *) &lvalue, sizeof(UINT4));
798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    buf += length;
808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    total_length += length+8;
818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    break;
828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		default:
838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    break;
848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    } else {
868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		*buf++ = vp->attribute;
878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		switch (vp->attribute) {
888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		case PW_USER_PASSWORD:
898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    /* Encrypt the password */
918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    /* Chop off password at AUTH_PASS_LEN */
938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    length = vp->lvalue;
948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    if (length > AUTH_PASS_LEN) length = AUTH_PASS_LEN;
958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    /* Calculate the padded length */
978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    padded_length = (length+(AUTH_VECTOR_LEN-1)) & ~(AUTH_VECTOR_LEN-1);
988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    /* Record the attribute length */
1008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    *buf++ = padded_length + 2;
1018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    /* Pad the password with zeros */
1038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    memset ((char *) passbuf, '\0', AUTH_PASS_LEN);
1048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    memcpy ((char *) passbuf, vp->strvalue, (size_t) length);
1058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    secretlen = strlen (secret);
1078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    vector = (char *)auth->vector;
1088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    for(i = 0; i < padded_length; i += AUTH_VECTOR_LEN) {
1098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			/* Calculate the MD5 digest*/
1108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			strcpy ((char *) md5buf, secret);
1118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			memcpy ((char *) md5buf + secretlen, vector,
1128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project				AUTH_VECTOR_LEN);
1138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			rc_md5_calc (buf, md5buf, secretlen + AUTH_VECTOR_LEN);
1148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			/* Remeber the start of the digest */
1168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			vector = buf;
1178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			/* Xor the password into the MD5 digest */
1198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			for (pc = i; pc < (i + AUTH_VECTOR_LEN); pc++) {
1208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			    *buf++ ^= passbuf[pc];
1218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			}
1228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    }
1238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    total_length += padded_length + 2;
1258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    break;
1278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#if 0
1288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		case PW_CHAP_PASSWORD:
1298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    *buf++ = CHAP_VALUE_LENGTH + 2;
1318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    /* Encrypt the Password */
1338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    length = vp->lvalue;
1348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    if (length > CHAP_VALUE_LENGTH) {
1358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			length = CHAP_VALUE_LENGTH;
1368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    }
1378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    memset ((char *) passbuf, '\0', CHAP_VALUE_LENGTH);
1388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    memcpy ((char *) passbuf, vp->strvalue, (size_t) length);
1398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    /* Calculate the MD5 Digest */
1418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    secretlen = strlen (secret);
1428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    strcpy ((char *) md5buf, secret);
1438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    memcpy ((char *) md5buf + secretlen, (char *) auth->vector,
1448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			    AUTH_VECTOR_LEN);
1458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    rc_md5_calc (buf, md5buf, secretlen + AUTH_VECTOR_LEN);
1468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    /* Xor the password into the MD5 digest */
1488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    for (i = 0; i < CHAP_VALUE_LENGTH; i++) {
1498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			*buf++ ^= passbuf[i];
1508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    }
1518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    total_length += CHAP_VALUE_LENGTH + 2;
1528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    break;
1548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
1558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		default:
1568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    switch (vp->type) {
1578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    case PW_TYPE_STRING:
1588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			length = vp->lvalue;
1598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			*buf++ = length + 2;
1608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			memcpy (buf, vp->strvalue, (size_t) length);
1618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			buf += length;
1628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			total_length += length + 2;
1638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			break;
1648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    case PW_TYPE_INTEGER:
1668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    case PW_TYPE_IPADDR:
1678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			*buf++ = sizeof (UINT4) + 2;
1688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			lvalue = htonl (vp->lvalue);
1698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			memcpy (buf, (char *) &lvalue, sizeof (UINT4));
1708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			buf += sizeof (UINT4);
1718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			total_length += sizeof (UINT4) + 2;
1728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			break;
1738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    default:
1758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			break;
1768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    }
1778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    break;
1788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
1798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
1808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    vp = vp->next;
1818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return total_length;
1838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
1868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Function: rc_send_server
1878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
1888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Purpose: send a request to a RADIUS server and wait for the reply
1898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
1908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
1918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectint rc_send_server (SEND_DATA *data, char *msg, REQUEST_INFO *info)
1938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int             sockfd;
1958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct sockaddr salocal;
1968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct sockaddr saremote;
1978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct sockaddr_in *sin;
1988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	struct timeval  authtime;
1998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	fd_set          readfds;
2008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	AUTH_HDR       *auth, *recv_auth;
2018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	UINT4           auth_ipaddr;
2028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char           *server_name;	/* Name of server to query */
2038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int             salen;
2048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int             result;
2058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int             total_length;
2068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int             length;
2078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int             retry_max;
2088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int		secretlen;
2098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char            secret[MAX_SECRET_LENGTH + 1];
2108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned char   vector[AUTH_VECTOR_LEN];
2118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char            recv_buffer[BUFFER_LEN];
2128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	char            send_buffer[BUFFER_LEN];
2138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int		retries;
2148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	VALUE_PAIR	*vp;
2158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	server_name = data->server;
2178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (server_name == (char *) NULL || server_name[0] == '\0')
2188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return (ERROR_RC);
2198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((vp = rc_avpair_get(data->send_pairs, PW_SERVICE_TYPE)) && \
2218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    (vp->lvalue == PW_ADMINISTRATIVE))
2228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
2238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		strcpy(secret, MGMT_POLL_SECRET);
2248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if ((auth_ipaddr = rc_get_ipaddr(server_name)) == 0)
2258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			return (ERROR_RC);
2268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
2278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	else
2288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
2298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (rc_find_server (server_name, &auth_ipaddr, secret) != 0)
2308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		{
2318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			return (ERROR_RC);
2328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
2338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
2348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sockfd = socket (AF_INET, SOCK_DGRAM, 0);
2368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (sockfd < 0)
2378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
2388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		memset (secret, '\0', sizeof (secret));
2398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		error("rc_send_server: socket: %s", strerror(errno));
2408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return (ERROR_RC);
2418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
2428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	length = sizeof (salocal);
2448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sin = (struct sockaddr_in *) & salocal;
2458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memset ((char *) sin, '\0', (size_t) length);
2468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sin->sin_family = AF_INET;
2471286c078a4b93695b3812e8c7fe7918c28ea18b4Adam Langley	sin->sin_addr.s_addr = htonl(rc_own_bind_ipaddress());
2488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sin->sin_port = htons ((unsigned short) 0);
2498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (bind (sockfd, (struct sockaddr *) sin, length) < 0 ||
2508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   getsockname (sockfd, (struct sockaddr *) sin, &length) < 0)
2518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
2528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		close (sockfd);
2538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		memset (secret, '\0', sizeof (secret));
2548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		error("rc_send_server: bind: %s: %m", server_name);
2558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return (ERROR_RC);
2568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
2578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	retry_max = data->retries;	/* Max. numbers to try for reply */
2598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	retries = 0;			/* Init retry cnt for blocking call */
2608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Build a request */
2628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	auth = (AUTH_HDR *) send_buffer;
2638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	auth->code = data->code;
2648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	auth->id = data->seq_nbr;
2658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (data->code == PW_ACCOUNTING_REQUEST)
2678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
2688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		total_length = rc_pack_list(data->send_pairs, secret, auth) + AUTH_HDR_LEN;
2698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		auth->length = htons ((unsigned short) total_length);
2718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		memset((char *) auth->vector, 0, AUTH_VECTOR_LEN);
2738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		secretlen = strlen (secret);
2748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		memcpy ((char *) auth + total_length, secret, secretlen);
2758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rc_md5_calc (vector, (char *) auth, total_length + secretlen);
2768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN);
2778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
2788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	else
2798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
2808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		rc_random_vector (vector);
2818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		memcpy (auth->vector, vector, AUTH_VECTOR_LEN);
2828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		total_length = rc_pack_list(data->send_pairs, secret, auth) + AUTH_HDR_LEN;
2848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		auth->length = htons ((unsigned short) total_length);
2868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
2878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sin = (struct sockaddr_in *) & saremote;
2898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memset ((char *) sin, '\0', sizeof (saremote));
2908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sin->sin_family = AF_INET;
2918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sin->sin_addr.s_addr = htonl (auth_ipaddr);
2928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	sin->sin_port = htons ((unsigned short) data->svc_port);
2938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	for (;;)
2958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
2968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		sendto (sockfd, (char *) auth, (unsigned int) total_length, (int) 0,
2978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			(struct sockaddr *) sin, sizeof (struct sockaddr_in));
2988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
2998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		authtime.tv_usec = 0L;
3008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		authtime.tv_sec = (long) data->timeout;
3018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		FD_ZERO (&readfds);
3028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		FD_SET (sockfd, &readfds);
3038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (select (sockfd + 1, &readfds, NULL, NULL, &authtime) < 0)
3048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		{
3058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			if (errno == EINTR)
3068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project				continue;
3078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			error("rc_send_server: select: %m");
3088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			memset (secret, '\0', sizeof (secret));
3098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			close (sockfd);
3108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			return (ERROR_RC);
3118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
3128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (FD_ISSET (sockfd, &readfds))
3138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			break;
3148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		/*
3168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		 * Timed out waiting for response.  Retry "retry_max" times
3178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		 * before giving up.  If retry_max = 0, don't retry at all.
3188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		 */
3198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (++retries >= retry_max)
3208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		{
3218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			error("rc_send_server: no reply from RADIUS server %s:%u",
3228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			      rc_ip_hostname (auth_ipaddr), data->svc_port);
3238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			close (sockfd);
3248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			memset (secret, '\0', sizeof (secret));
3258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			return (TIMEOUT_RC);
3268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
3278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
3288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	salen = sizeof (saremote);
3298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	length = recvfrom (sockfd, (char *) recv_buffer,
3308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			   (int) sizeof (recv_buffer),
3318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			   (int) 0, &saremote, &salen);
3328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (length <= 0)
3348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
3358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		error("rc_send_server: recvfrom: %s:%d: %m", server_name,\
3368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		      data->svc_port);
3378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		close (sockfd);
3388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		memset (secret, '\0', sizeof (secret));
3398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return (ERROR_RC);
3408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
3418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	recv_auth = (AUTH_HDR *)recv_buffer;
3438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	result = rc_check_reply (recv_auth, BUFFER_LEN, secret, vector, data->seq_nbr);
3458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	data->receive_pairs = rc_avpair_gen(recv_auth);
3478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	close (sockfd);
3498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (info)
3508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
3518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		memcpy(info->secret, secret, sizeof(info->secret));
3528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		memcpy(info->request_vector, vector,
3538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		       sizeof(info->request_vector));
3548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
3558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memset (secret, '\0', sizeof (secret));
3568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (result != OK_RC) return (result);
3588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	*msg = '\0';
3608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	vp = data->receive_pairs;
3618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	while (vp)
3628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
3638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if ((vp = rc_avpair_get(vp, PW_REPLY_MESSAGE)))
3648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		{
3658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			strcat(msg, vp->strvalue);
3668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			strcat(msg, "\n");
3678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			vp = vp->next;
3688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
3698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
3708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((recv_auth->code == PW_ACCESS_ACCEPT) ||
3728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		(recv_auth->code == PW_PASSWORD_ACK) ||
3738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		(recv_auth->code == PW_ACCOUNTING_RESPONSE))
3748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
3758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		result = OK_RC;
3768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
3778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	else
3788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
3798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		result = BADRESP_RC;
3808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
3818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return (result);
3838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
3848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
3868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Function: rc_check_reply
3878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
3888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Purpose: verify items in returned packet.
3898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
3908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Returns:	OK_RC       -- upon success,
3918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *		BADRESP_RC  -- if anything looks funny.
3928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
3938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
3948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
3958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic int rc_check_reply (AUTH_HDR *auth, int bufferlen, char *secret,
3968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			   unsigned char *vector, unsigned char seq_nbr)
3978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
3988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int             secretlen;
3998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int             totallen;
4008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned char   calc_digest[AUTH_VECTOR_LEN];
4018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	unsigned char   reply_digest[AUTH_VECTOR_LEN];
4028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	totallen = ntohs (auth->length);
4048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	secretlen = strlen (secret);
4068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Do sanity checks on packet length */
4088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((totallen < 20) || (totallen > 4096))
4098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
4108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		error("rc_check_reply: received RADIUS server response with invalid length");
4118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return (BADRESP_RC);
4128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Verify buffer space, should never trigger with current buffer size and check above */
4158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((totallen + secretlen) > bufferlen)
4168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
4178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		error("rc_check_reply: not enough buffer space to verify RADIUS server response");
4188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return (BADRESP_RC);
4198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Verify that id (seq. number) matches what we sent */
4218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (auth->id != seq_nbr)
4228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
4238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		error("rc_check_reply: received non-matching id in RADIUS server response");
4248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return (BADRESP_RC);
4258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	/* Verify the reply digest */
4288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy ((char *) reply_digest, (char *) auth->vector, AUTH_VECTOR_LEN);
4298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy ((char *) auth->vector, (char *) vector, AUTH_VECTOR_LEN);
4308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	memcpy ((char *) auth + totallen, secret, secretlen);
4318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	rc_md5_calc (calc_digest, (char *) auth, totallen + secretlen);
4328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef DIGEST_DEBUG
4348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
4358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		int i;
4368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		fputs("reply_digest: ", stderr);
4388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		for (i = 0; i < AUTH_VECTOR_LEN; i++)
4398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		{
4408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			fprintf(stderr,"%.2x ", (int) reply_digest[i]);
4418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
4428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		fputs("\ncalc_digest:  ", stderr);
4438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		for (i = 0; i < AUTH_VECTOR_LEN; i++)
4448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		{
4458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			fprintf(stderr,"%.2x ", (int) calc_digest[i]);
4468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
4478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		fputs("\n", stderr);
4488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
4508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (memcmp ((char *) reply_digest, (char *) calc_digest,
4528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		    AUTH_VECTOR_LEN) != 0)
4538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
4548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#ifdef RADIUS_116
4558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		/* the original Livingston radiusd v1.16 seems to have
4568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   a bug in digest calculation with accounting requests,
4578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   authentication request are ok. i looked at the code
4588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   but couldn't find any bugs. any help to get this
4598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   kludge out are welcome. preferably i want to
4608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   reproduce the calculation bug here to be compatible
4618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		   to stock Livingston radiusd v1.16.	-lf, 03/14/96
4628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		 */
4638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		if (auth->code == PW_ACCOUNTING_RESPONSE)
4648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			return (OK_RC);
4658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#endif
4668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		error("rc_check_reply: received invalid reply digest from RADIUS server");
4678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return (BADRESP_RC);
4688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
4698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return (OK_RC);
4718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
4738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
4758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Function: rc_random_vector
4768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
4778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Purpose: generates a random vector of AUTH_VECTOR_LEN octets.
4788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
4798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project * Returns: the vector (call by reference)
4808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project *
4818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project */
4828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void rc_random_vector (unsigned char *vector)
4848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
4858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int             randno;
4868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int             i;
4878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	int		fd;
4888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/* well, I added this to increase the security for user passwords.
4908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project   we use /dev/urandom here, as /dev/random might block and we don't
4918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project   need that much randomness. BTW, great idea, Ted!     -lf, 03/18/95	*/
4928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((fd = open(_PATH_DEV_URANDOM, O_RDONLY)) >= 0)
4948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
4958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		unsigned char *pos;
4968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		int readcount;
4978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
4988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		i = AUTH_VECTOR_LEN;
4998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		pos = vector;
5008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		while (i > 0)
5018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		{
5028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			readcount = read(fd, (char *)pos, i);
5038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			pos += readcount;
5048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			i -= readcount;
5058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		}
5068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		close(fd);
5088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
5098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	} /* else fall through */
5108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	for (i = 0; i < AUTH_VECTOR_LEN;)
5128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	{
5138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		randno = magic();
5148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		memcpy ((char *) vector, (char *) &randno, sizeof (int));
5158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		vector += sizeof (int);
5168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		i += sizeof (int);
5178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
5188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
5198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return;
5208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
521