sendserver.c
来自「RADIUS协议的认证计费服务」· C语言 代码 · 共 939 行 · 第 1/2 页
C
939 行
sin->sin_family = AF_INET; sin->sin_addr.s_addr = htonl(auth_ipaddr); sin->sin_port = htons(data->svc_port); for (;;) { /* * Retransmission loop. */ if (debug_flag >= 2) { dumpit (LOG_DAEMON, LOG_DEBUG, (u_char *) auth, total_length, 0, "%s: sending packet to %s:%d", func, inet_ntoa(sin->sin_addr), ntohs(sin->sin_port)); } sendto (sockfd, (char *) auth, (int) total_length, (int) 0, (struct sockaddr *) sin, sizeof (struct sockaddr_in)); if (radsock >= 0) { /* If non-blocking */ /* * Return stuff to be saved for evaluation * of reply when it comes in. */ strcpy (msg, secret); memcpy (msg + strlen (msg) + 1, (char *) vector, AUTH_VECTOR_LEN); return 1; /* Positive return means no error */ } authtime.tv_usec = 0L; authtime.tv_sec = (long) timeout; FD_ZERO (&readfds); FD_SET (sockfd, &readfds); if (select (sockfd + 1, &readfds, NULL, NULL, &authtime) < 0) { if (errno == EINTR) continue; sprintf (msg, "select: %s\n", sys_errlist[errno]); /* XXX close (sockfd); */ return (ERROR_RC); } if (FD_ISSET (sockfd, &readfds)) { break; } /* * Timed out waiting for response. Retry "retry_max" times * before giving up. If retry_max = 0, don't retry at all. */ if (++(*retries) >= retry_max) { if (debug_flag > 0) { fprintf (stderr, "\n"); } sprintf (msg, "No reply from RADIUS server \"%s(%u)\"\n", ip_hostname (auth_ipaddr), data->svc_port); /* XXX close (sockfd); */ return (TIMEOUT_RC); } else { if (debug_flag > 0) { fprintf (stderr, "."); } } } salen = sizeof (saremote); len = recvfrom (sockfd, recv_buffer, (int) sizeof (recv_buffer) - MAX_SECRET_LENGTH, (int) 0, &saremote, &salen); if (len <= 0) { sprintf (msg, "recvfrom: %s\n", sys_errlist[errno]); /* XXX close (sockfd); */ return (ERROR_RC); } length = len; /* * More debugging */ if (debug_flag >= 2) { dumpit (LOG_DAEMON, LOG_DEBUG, (u_char *) recv_buffer, length, 0, "%s: received reply", func); } result = check_radius_reply ((u_char *) recv_buffer, length, secret, (u_char *) vector, seq_nbr, data, msg); /* XXX close (sockfd); */ return (result);} /* end of send_server () *//************************************************************************* * * Function: check_radius_reply * * Purpose: Verify items in returned packet. * * Returns: OK_RC -- upon success, * BADRESP_RC -- if anything looks funny. * **************************************************************************/static int check_radius_reply (buffer, len, secret, vector, seq_nbr, data, msg)u_char *buffer;u_int len;char *secret;u_char *vector;UINT4 seq_nbr;SEND_DATA *data;char *msg;{ int result; int secretlen; int totallen; int version; u_short code; u_short rcv_id; AUTH_HDR *auth; AUTH_HDR1 *ah1; VALUE_PAIR *vp; VALUE_PAIR *rep_vp; u_char calc_digest[AUTH_VECTOR_LEN]; u_char reply_digest[AUTH_VECTOR_LEN]; auth = (AUTH_HDR *) buffer; if (auth->code == PW_EXTENDED_FORMAT) { rcv_id = ntohs(auth->id); code = ntohs(auth->command); version = auth->flag_ver & AUTH_HDR_VERSION_BITS; totallen = ntohs(auth->length); if ((result = check_mic (auth, totallen, secret, (CLIENT_ENTRY *) NULL)) != 0) { sprintf (msg, "Received invalid %s in reply", result < 0 ? "MIC" : "TIMESTAMP"); return (BADRESP_RC); } } else { ah1 = (AUTH_HDR1 *) auth; code = ah1->code; rcv_id = ah1->id; version = VER1; totallen = ntohs(ah1->length); memcpy ((char *) reply_digest, (char *) ah1->vector, AUTH_VECTOR_LEN); memcpy ((char *) ah1->vector, (char *) vector, AUTH_VECTOR_LEN); secretlen = strlen (secret); memcpy (buffer + totallen, secret, secretlen); md5_calc (calc_digest, (char *) auth, totallen + secretlen); if (memcmp ((char *) reply_digest, (char *) calc_digest, AUTH_VECTOR_LEN) != 0) { sprintf (msg, "Received invalid reply digest from server\n"); return (BADRESP_RC); } seq_nbr = (u_char) seq_nbr; } if (totallen > len) { sprintf (msg, "Received poorly formed packet (length = %d)\n", len); return (BADRESP_RC); } if (seq_nbr != rcv_id) { sprintf (msg, "Received non-matching id in server response\n"); return (BADRESP_RC); } if (debug_flag) { fprintf (stderr, "Received attribute/value pair(s):\n"); } vp = gen_valpairs (auth, len, (VENDOR_LIST *) NULL, GVP_SILENT); msg[0] = '\0'; for (rep_vp = get_vp (vp, PW_REPLY_MESSAGE); rep_vp != NULL_VP; rep_vp = get_vp (rep_vp->next, PW_REPLY_MESSAGE)) { strcat (msg, rep_vp->strvalue); strcat (msg, "\n"); /* Artificial newline. */ } /* Acceptable return code */ if ((code == PW_ACCESS_ACCEPT) || (code == PW_PASSWORD_ACK) || (code == PW_ACCESS_CHALLENGE) ||#ifdef ASCEND (code == PW_PASSWORD_EXPIRED) ||#endif /* ASCEND */ (code == PW_ACCOUNTING_RESPONSE)) { result = OK_RC; } else { result = BADRESP_RC; } data->result = code; /* Report any attributes returned from the remote RADIUS server */ if (data->receive_pairs == NULL_VP) { data->receive_pairs = vp; } else { list_cat (&data->receive_pairs, vp); } return (result);} /* end of check_radius_reply *//************************************************************************* * * Function: find_match * * Purpose: See if given IP address matches any address of hostname. * * Returns: 0 success * -1 failure * **************************************************************************/static int find_match (ip_addr, hostname)UINT4 *ip_addr;char *hostname;{ UINT4 addr; char *ptr; char **paddr; struct hostent *hp; char hn[255]; strcpy (hn, hostname); if ((ptr = (char *) strtok (hn, " :\t\n\r")) == (char *) NULL) { return (-1); } if (good_ipaddr (ptr) == 0) { if (*ip_addr == ntohl(inet_addr (ptr))) { return (0); } } else { if ((hp = gethostbyname (ptr)) == (struct hostent *) NULL) { return (-1); } if (hp->h_addr_list != (char **) NULL) { for (paddr = hp->h_addr_list; *paddr; paddr++) { addr = ** (UINT4 **) paddr; if (ntohl(addr) == *ip_addr) { return (0); } } } } return (-1);} /* end of find_match *//************************************************************************* * * Function: find_server * * Purpose: Look up the given server name in the clients file. * * Returns: 0 success * -1 failure * **************************************************************************/static int find_server (server_name, ustype, ip_addr, secret, msg)char *server_name;int ustype;UINT4 *ip_addr;char *secret;char *msg;{ static UINT4 myipaddr = 0; int len; int line_nbr = 0; int result; FILE *clientfd; char *h; char *s; char *host2; char buffer[128]; char fname[MAXPATHLEN]; char hostnm[AUTH_ID_LEN + 1]; /* Get the IP address of the authentication server */ if ((*ip_addr = get_ipaddr (server_name)) == (UINT4) 0) { sprintf (msg, "No such server: \"%s\"\n", server_name); return (-1); } /* Just use dummy secret for management polls */ if (ustype == PW_ADMINISTRATIVE_USER) /* was old PW_MANAGEMENT_POLL */ { strcpy (secret, MGMT_POLL_SECRET); return 0; } sprintf (fname, "%s/%s", radius_dir, RADIUS_CLIENTS); if ((clientfd = fopen (fname, "r")) == (FILE *) NULL) { sprintf (msg, "Couldn't open file \"%s\"\n", fname); return (-1); } if (!myipaddr) { if ((myipaddr = get_ipaddr (ourhostname)) == 0) { sprintf (msg, "Couldn't get our own ip address\n"); fclose (clientfd); return (-1); } } result = 0; while (fgets (buffer, sizeof (buffer), clientfd) != (char *) NULL) { line_nbr++; if (*buffer == '#') { continue; } /* First hostname... */ if ((h = (char *) strtok (buffer, " \t\n\r")) == NULL) { continue; } memset (hostnm, '\0', AUTH_ID_LEN); len = strlen (h); if (len > AUTH_ID_LEN) { len = AUTH_ID_LEN; } strncpy (hostnm, h, len); hostnm[AUTH_ID_LEN] = '\0'; /* ... and secret field */ if ((s = (char *) strtok (NULL, " \t\n\r")) == NULL) { continue; } memset (secret, '\0', MAX_SECRET_LENGTH); len = strlen (s); if (len > MAX_SECRET_LENGTH) { len = MAX_SECRET_LENGTH; } strncpy (secret, s, len); secret[MAX_SECRET_LENGTH] = '\0'; if (!strchr (hostnm, '/')) /* If single name form */ { if (find_match (ip_addr, hostnm) == 0) { result++; break; } } else /* <name1>/<name2> "paired" form */ { strtok (hostnm, "/"); /* replaces "/" with NULL char */ host2 = (char *) strtok (NULL, " "); if (find_match (&myipaddr, hostnm) == 0) { /* If we're the 1st name, target is 2nd */ if (find_match (ip_addr, host2) == 0) { result++; break; } } else /* Check to see if we are the second name */ { if (find_match (&myipaddr, host2) == 0) { /* We are the 2nd name, target is 1st name */ if (find_match (ip_addr, hostnm) == 0) { result++; break; } } } } } fclose (clientfd); if (result == 0) { memset (buffer, '\0', sizeof (buffer)); memset (secret, '\0', sizeof (secret)); sprintf (msg, "Couldn't find server in \"%s/%s\": \"%s\"\n", radius_dir, RADIUS_CLIENTS, server_name); return (-1); } return 0;} /* end of find_server () *//************************************************************************* * * Function: send_server_done * * Purpose: Clean up after done with send_server(). * **************************************************************************/voidsend_server_done (){ if (sockfd >= 0) { close (sockfd); } return;} /* end of send_server_done () */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?