📄 users.c
字号:
UINT4 addr; UINT4 *adptr; IP_ADDRESS *each_ip; if (ce != (CLIENT_ENTRY *) NULL) { for (each_ip = ce->addrs; each_ip != (IP_ADDRESS *) NULL; each_ip = each_ip->next) { addr = ntohl(each_ip->ipaddr.s_addr); for (adptr = self_ip; *adptr > 0; adptr++) { if (*adptr == addr) { return 1; } } } } return 0;} /* end of client_is_us () *//************************************************************************* * * Function: client_queue_size * * Purpose: Returns count of events queued up for the given client. * * Returns: count of queued events, * 0 otherwise. * *************************************************************************/intclient_queue_size (cli)CLIENT_ENTRY *cli;{ int i = 0; EVENT_ENT *event; static char *func = "client_queue_size"; if (cli == (CLIENT_ENTRY *) NULL) { return 0; } for (event = cli->event_q; event != (EVENT_ENT *) NULL; event = event->client_next) { i++; /* Count the event queued here. */ } return i;} /* end of client_queue_size () *//************************************************************************* * * Function: config_files * * Purpose: Read database files into memory data structures. Reads * "RADIUS_CLIENTS" and "RADIUS_AUTH" files unconditionally * and "RADIUS_USERS" file if users_flag is not zero. Will * read multiple users and authfiles if the "file_pfx" is * specified in a client entry (allowing use of different * files for different client NASes). * * If clear_flag is greater than zero, remove existing entries. * * A new CLIENT_ENTRY is added to the client_list for each * client appearing in the "RADIUS_CLIENTS" file. A new * FILE_LIST entry is added for each unique file_pfx found * in the "RADIUS_CLIENTS" file. Each FILE_LIST entry points * to a list of USER_ENTRYs containing the information read * from the "RADIUS_USERS" file with the corresponding * file_pfx. Also each FILE_LIST entry contains a pointer to * the list of AUTH_ENTRYs containing realm information read * from the "RADIUS_AUTH" file with the corresponding file_pfx. * If either the "RADIUS_USERS" file or the "RADIUS_AUTH" file * with the given file_pfx did not exist, the default * (non-prefixed) file name entries are used instead. * *************************************************************************/intconfig_files (users_flag, clear_flag, dolog)int users_flag;int clear_flag;int dolog;{ int i; int result; FILE_LIST *file_ent; struct hostent *hp; char **paddr; static char *func = "config_files"; dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: entered", func)); if (clear_flag > 0) /* Free current list, if already set up */ { free_file_lists (); } authfile_id[0] = '\0'; clients_id[0] = '\0'; /* * Add default file_list entry - the entry for the "users" and * "authfile" with no optional prefix */ add_file_list (""); /* * Determine the IP address(es) of this machine * * NOTE: This could hang for a while! */ if ((hp = gethostbyname (ourhostname)) == (struct hostent *) NULL) { logit (LOG_DAEMON, LOG_CRIT, "%s: Couldn't get our own IP address(es)", func); return (-1); } /* * First clear, then save our IP address(es) * leaving a zero entry at the end. */ memset ((char *) self_ip, '\0', sizeof (self_ip)); if (hp->h_addr_list != (char **) NULL) { for (i = 0, paddr = hp->h_addr_list; (*paddr != (char *) NULL) && (i < sizeof (self_ip) / 4 - 1); i++, paddr++) { memcpy ((char *) &self_ip[i], (char *) *paddr, hp->h_length); self_ip[i] = ntohl(self_ip[i]); } } /* * Release /etc/resolv.conf (hopefully). */ endhostent (); if ((result = read_clients (dolog)) < 0) { logit (LOG_DAEMON, LOG_ERR, "%s: FATAL error '%d' from read_clients()", func, result); return (-1); } /* * Finally, go through all the file_list entries just added, reading * in the "users" and "authfile" for each prefix found. */ for (file_ent = file_list; file_ent; file_ent = file_ent->next) {#if !(defined(USE_DBM) || defined(USE_NDBM)) if (users_flag) if (read_users (file_ent, dolog) != 0) { return (-1); }#endif /* USE_DBM || USE_NDBM */ if (read_auth (file_ent, dolog) != 0) { return (-1); } } if (result < 0) { return (-1); } return 0;} /* end of config_files () *//************************************************************************* * * Function: config_fini * * Purpose: Cleanup environment after config_files() has run. * *************************************************************************/voidconfig_fini (){ free_clients (old_clients); old_clients = (CLIENT_ENTRY *) NULL; if ((file_logging == 1) && (msgfd != (FILE *) NULL)) { fflush (msgfd); } if (dnspid == -1) { dnspid = 0; } update_clients (); /* Start up the DNS resolver. */ doing_init = 0; /* Done with initialization */ return;} /* end of config_fini () *//************************************************************************* * * Function: config_init * * Purpose: Setup environment for config_files() to run in. * *************************************************************************/voidconfig_init (){ is_engine = 1; /* flag set when engine calls us */ /* * Set dnspid to defer the call to update_clients() * until the end of config_files(). */ if (dnspid == 0) { dnspid = -1; } doing_init = 1; /* Indicate we're doing initialization */ /* * Save the old clients list so we can pick up * the DNS addresses for the new list. */ old_clients = client_list; client_list = (CLIENT_ENTRY *) NULL; return;} /* end of config_init () *//************************************************************************* * * Function: dns_recv * * Purpose: Process received DNS updates for clients database. * *************************************************************************/voiddns_recv (sin, from_ipaddr, rcvlen)struct sockaddr_in *sin;UINT4 from_ipaddr;int rcvlen;{ u_char aliascnt; int cnt; int count; UINT4 temp; UINT4 *ourad; char *ptr; IP_ADDRESS *an_address; DNS_NAME *a_name; CLIENT_ENTRY *client_ent; static int notify_count = 0; static char *func = "dns_recv"; notify_count++; dprintf(4, (LOG_AUTH, LOG_DEBUG, "%s: entered (%d)", func, notify_count)); ddumpx(3, (LOG_DAEMON, LOG_DEBUG, recv_buffer, rcvlen, 0, "%s: Packet received from %s", func, ip_hostname (from_ipaddr))); /* Reset client_ent cache. */ last_client_found = (CLIENT_ENTRY *) NULL; last_client_name = (char *) NULL; last_client_ipaddr = 0; ptr = recv_buffer + 1; for (ourad = self_ip; (*ourad != (UINT4) 0) && (*ourad != from_ipaddr); ourad++) { continue; } if (*ourad == (UINT4) 0) { logit (LOG_DAEMON, LOG_INFO, "%s: from %s - Security Breach", func, ip_hostname (from_ipaddr)); return; } for (client_ent = client_list; client_ent != (CLIENT_ENTRY *) NULL; client_ent = client_ent->next) { if (strcmp (ptr, client_ent->hostname) == 0) { break; } } if (client_ent == (CLIENT_ENTRY *) NULL) { return; } ptr += strlen (ptr) + 1; /* Point over name */ aliascnt = *ptr++; if (*ptr != '\0') /* If alias or IP address present, clear old ones */ { /* * Reset expire_time with some randomness (0 - 60 minutes) * to avoid a burst of calls to gethostbyname(). * * [0, 1, 2, 3] * 1200 == [0, 1200, 2400, 3600] */ client_ent->expire_time = (time (0) + dns_address_aging + (rand () & 3) * 60 * 20) & ~3; dprintf(2, (LOG_AUTH, LOG_DEBUG, "%s: expire time = 0x%08X", func, client_ent->expire_time)); for (an_address = client_ent->addrs; an_address != (IP_ADDRESS *) NULL; an_address = client_ent->addrs) { client_ent->addrs = an_address->next; free (an_address); dns_addr_mf.f++; } for (a_name = client_ent->names; a_name != (DNS_NAME *) NULL; a_name = client_ent->names) { client_ent->names = a_name->next; free (a_name); dns_name_mf.f++; } } else /* no alias or IP address present */ { memcpy ((char *) &temp, ptr, sizeof (struct in_addr)); if (temp == TRY_AGAIN) /* TRY_AGAIN is in netdb.h */ { client_ent->expire_time = (time (0) + dns_address_aging) & ~3; logit (LOG_DAEMON, LOG_ALERT, "%s: DNS timeout on client or host '%s'", func, client_ent->hostname); return; } else { /* * Name couldn't be resolved -- log it and retry * shortly. Cleverly (or foolishly) use the low * two bits of expire_time to control the logging * frequency. */ if ((cnt = client_ent->expire_time & 3) == 0) { /* Log every fourth time (or once per hour) */ logit (LOG_DAEMON, LOG_ALERT, "%s: DNS couldn't resolve name '%s' (%ld)", func, client_ent->hostname, temp); } client_ent->expire_time = ((time (0) + (dns_address_aging / 4)) & ~3) | (++cnt & 3); if (client_ent->addrs != (IP_ADDRESS *) NULL) { return; } /* Add invalid address to client_ent */ memset (ptr, 255, sizeof (struct in_addr)); } } /* Add alias names to client_ent structure */ count = 0; while (aliascnt-- > 0) { count++; if (count > MAX_ALIAS) { logit (LOG_DAEMON, LOG_ALERT, "%s: FATAL: Too many aliases for client '%s'", func, client_ent->hostname); abort (); } /* Note that DNS_NAME structure reserves one extra character. */ a_name = (DNS_NAME *) get_memory (sizeof (DNS_NAME) + strlen (ptr), func, "DNS_NAME"); dns_name_mf.m++; /* Note that type zero will always be the last one. */ strcpy (a_name->name, ptr); ptr += strlen (ptr) + 1; a_name->type = (u_char) *ptr++; a_name->next = client_ent->names; client_ent->names = a_name; } /* * For each address in the list, add the address to the client_ent. */ while (*ptr != '\0') { an_address = (IP_ADDRESS *) get_memory (sizeof (IP_ADDRESS), func, "IP_ADDRESS"); dns_addr_mf.m++; an_address->next = client_ent->addrs; memcpy ((char *) &temp, ptr, sizeof (struct in_addr)); an_address->ipaddr.s_addr = ntohl(temp); client_ent->addrs = an_address; ptr += sizeof (struct in_addr); } if ((notify_count % DNS_SLEEP) == 0) { logit (LOG_DAEMON, LOG_INFO, "%s: Notified of (%d) DNS changes", func, notify_count); } return;} /* end of dns_recv () *//************************************************************************* * * Function: fieldcpy * * Purpose: Copy a data field from the buffer to which "uptr" points. * Advance the buffer past the data field. * * Returns: actual length of the data field, * or -1, if error. * *************************************************************************/static intfieldcpy (string, uptr, len)char *string; /* Receiving buffer. */char **uptr; /* Pointer to original data passed in. */int len; /* Size of receiving buffer "string" */{ int accum; int count; char *beg_string; char *end; char *end_tag; /* end of tag in data string */ char *ptr; char hex_buf[4]; /* 2 hex digits or 3 octal digits */ static char *func = "fieldcpy"; ptr = *uptr; end = string + len - 1; /* Leave room for NULL character at end. */ beg_string = string; /* Tagged attribute values are of the form :<tag>:<value> */ if (*ptr == ':') { ptr++; /* Skip leading colon character. */ if ((end_tag = strchr (ptr, ':')) == (char *) NULL) { logit (LOG_DAEMON, LOG_INFO, "%s: No terminating colon for tag in ':%s'", func, ptr); return (-1); } *end_tag = '\0'; accum = atoi (ptr); /* fieldcpy() tag value */ if ((accum < 0) || ( 255 < accum)) { logit (LOG_DAEMON, LOG_INFO, "%s: Tag '%s' (%d) out of range (0-255)", func, ptr, accum); return (-1); } *string = accum; /* Insert tag into buffer. */ string++; ptr = end_tag + 1; /* Position past tag. */ } /* Quoted attribute strings are of the form "<value>" */ if (*ptr == '"') { ptr++; /* Skip leading quote character. */ while (*ptr != '"' && *ptr != '\0' && *ptr != '\n') { if (*ptr == '\\') { accum = 0; count = 0; ptr++; /* octal conversion */ while ((count < 3) && (*ptr >= '0') && (*ptr <= '7')) { count++; accum = (accum << 3) + (*ptr++ - '0'); } if (count > 0) { *string++ = accum; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -