From af754e596a8dbb05ed8580c342e7fe02e08b28e0 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 13 Apr 2024 16:11:00 +0200 Subject: Adding upstream version 3.2.3+dfsg. Signed-off-by: Daniel Baumann --- src/modules/rlm_ippool/rlm_ippool_tool.c | 645 +++++++++++++++++++++++++++++++ 1 file changed, 645 insertions(+) create mode 100644 src/modules/rlm_ippool/rlm_ippool_tool.c (limited to 'src/modules/rlm_ippool/rlm_ippool_tool.c') diff --git a/src/modules/rlm_ippool/rlm_ippool_tool.c b/src/modules/rlm_ippool/rlm_ippool_tool.c new file mode 100644 index 0000000..94f6161 --- /dev/null +++ b/src/modules/rlm_ippool/rlm_ippool_tool.c @@ -0,0 +1,645 @@ +/* + * rlm_ippool_tool.c + * + * Version: $Id$ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * Copyright 2003, 2006 FreeRADIUS Project, http://www.freeradius.org/ + * Copyright 2003 Edwin Groothuis, edwin@mavetju.org + * Permission from Edwin Groothuis for release under GPL is archived here: + * http://lists.cistron.nl/archives/freeradius-devel/2003/09/frm00247.html + * + */ + +/* + The original license follows. This license applies to the tarball at + http://www.mavetju.org/unix/general.php + + Copyright 2003 by Edwin Groothuis, edwin@mavetju.org + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +RCSID("$Id$") + +#include +#include +#include +#include "../../include/md5.h" + +static int active = 0; + +static int aflag = 0; +static int cflag = 0; +static int rflag = 0; +static int vflag = 0; +static int nflag = 0; +static int oflag = 0; +static int uflag = 0; + +typedef struct ippool_info { + uint32_t ipaddr; + char active; + char cli[32]; + char extra; +} ippool_info; + + +#define MAX_NAS_NAME_SIZE 64 + +typedef struct old_ippool_key { + char nas[MAX_NAS_NAME_SIZE]; + uint16_t port; +} old_ippool_key; + +typedef struct ippool_key { + char key[16]; +} ippool_key; + +#define MATCH_IP(ip1, ip2) ((ip1) == NULL || strcmp((ip1), (ip2)) == 0) +#define MATCH_ACTIVE(info) ((info).active == 1 || !aflag) + +void addip(char *sessiondbname, char *indexdbname, char *ipaddress, + char *NASname, char *NASport, int old); + +void viewdb(char *sessiondbname, char *indexdbname, char *ipaddress, int old); + +void tonewformat(char *sessiondbname, char *newsessiondbname); + +void usage(char *argv0); + +void addip(char *sessiondbname, char *indexdbname, char *ipaddress, + char *NASname, char *NASport, int old) +{ + GDBM_FILE sessiondb; + GDBM_FILE indexdb; + datum key_datum, data_datum, save_datum; + datum nextkey; + + ippool_key key; + old_ippool_key old_key; + + ippool_info entry; + struct in_addr ipaddr; + uint8_t key_str[17]; + char hex_str[35]; + int num = 0; + int mppp = 0; + int mode = GDBM_WRITER; + int rcode; + int delete = 0; + uint16_t port; + bool found = false; + + memset(&key, 0, sizeof(key)); /* -Winitialize */ + + sessiondb = gdbm_open(sessiondbname, 512, mode, 0,NULL); + indexdb = gdbm_open(indexdbname, 512, mode, 0,NULL); + + if (inet_aton(ipaddress, &ipaddr) == 0) { + printf("rlm_ippool_tool: Unable to convert IP address '%s'\n", ipaddress); + return; + } + + if (!sessiondb) { + printf("rlm_ippool_tool: Unable to open DB '%s'\n", sessiondbname); + return; + } + + if (!indexdb) { + printf("rlm_ippool_tool: Unable to open DB '%s'\n", indexdbname); + return; + } + + port = strtoul(NASport, NULL, 0); + + /* Basically from rlm_ippool.c */ + + if (old){ + strlcpy(old_key.nas, NASname, sizeof(old_key.nas)); + old_key.port = port; + key_datum.dptr = (char *) &old_key; + key_datum.dsize = sizeof(old_ippool_key); + } else { + char md5_input_str[MAX_STRING_LEN]; + FR_MD5_CTX md5_context; + + snprintf(md5_input_str, MAX_STRING_LEN, "%s %s", NASname, NASport); + + fr_md5_init(&md5_context); + fr_md5_update(&md5_context, (uint8_t *) md5_input_str, strlen(md5_input_str)); + fr_md5_final(key_str, &md5_context); + + memcpy(key.key, key_str, 16); + fr_bin2hex(hex_str, key_str, 16); + hex_str[32] = '\0'; + key_datum.dptr = (char *) &key; + key_datum.dsize = sizeof(ippool_key); + } + + + data_datum = gdbm_fetch(sessiondb, key_datum); + if (data_datum.dptr != NULL){ + found = true; + memcpy(&entry, data_datum.dptr, sizeof(ippool_info)); + + if (entry.active){ + if (old) { + printf("rlm_ippool_tool: Deleting stale entry for ip/port %s/%u", + ipaddress, port); + } else { + printf("rlm_ippool_tool: Deleting stale entry for key: '%s'", hex_str); + } + + entry.active = 0; + save_datum.dptr = key_datum.dptr; + save_datum.dsize = key_datum.dsize; + + data_datum.dptr = (char*) &entry; + data_datum.dsize = sizeof(ippool_info); + + rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE); + if (rcode < 0) { + printf("rlm_ippool_tool: Failed storing data to %s: %s\n", + sessiondbname, gdbm_strerror(gdbm_errno)); + goto close; + } + + key_datum.dptr = (char *) &entry.ipaddr; + key_datum.dsize = sizeof(uint32_t); + data_datum = gdbm_fetch(indexdb, key_datum); + + if (data_datum.dptr != NULL) { + memcpy(&num, data_datum.dptr, sizeof(int)); + + if (num > 0) { + num--; + data_datum.dptr = (char *) # + data_datum.dsize = sizeof(int); + rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE); + + if (rcode < 0) { + printf("rlm_ippool_tool: Failed storing data to %s: %s\n", + indexdbname, gdbm_strerror(gdbm_errno)); + goto close; + } + + if (num > 0 && entry.extra == 1) { + gdbm_delete(sessiondb, save_datum); + } + } + } + } + } + key_datum.dptr = NULL; + + if (!key_datum.dptr) { + key_datum = gdbm_firstkey(sessiondb); + + while (key_datum.dptr) { + data_datum = gdbm_fetch(sessiondb, key_datum); + if (data_datum.dptr != NULL) { + memcpy(&entry, data_datum.dptr, sizeof(ippool_info)); + free(data_datum.dptr); + + if (entry.active == 0 && entry.ipaddr == ipaddr.s_addr) { + datum tmp; + tmp.dptr = (char *) &entry.ipaddr; + tmp.dsize = sizeof(uint32_t); + data_datum = gdbm_fetch(indexdb, tmp); + if (data_datum.dptr){ + memcpy(&num, data_datum.dptr, sizeof(int)); + free(data_datum.dptr); + if (num == 0){ + delete = 1; + break; + } + } else { + delete = 1; + break; + } + } + } + nextkey = gdbm_nextkey(sessiondb, key_datum); + free(key_datum.dptr); + key_datum = nextkey; + } + } + + if (key_datum.dptr){ + if (found && ! mppp){ + datum key_datum_tmp, data_datum_tmp; + old_ippool_key old_key_tmp; + ippool_key key_tmp; + + if (old){ + strlcpy(old_key_tmp.nas, NASname, + sizeof(old_key_tmp.nas)); + old_key_tmp.port = port; + key_datum_tmp.dptr = (char *) &old_key_tmp; + key_datum_tmp.dsize = sizeof(old_ippool_key); + } else { + memcpy(key_tmp.key, key_str, 16); + key_datum_tmp.dptr = (char *) &key_tmp; + key_datum_tmp.dsize = sizeof(ippool_key); + } + + data_datum_tmp = gdbm_fetch(sessiondb, key_datum_tmp); + if (data_datum_tmp.dptr != NULL) { + rcode = gdbm_store(sessiondb, key_datum, data_datum_tmp, GDBM_REPLACE); + if (rcode < 0) { + printf("rlm_ippool_tool: Failed storing data to %s: %s\n", + sessiondbname, gdbm_strerror(gdbm_errno)); + goto close; + } + free(data_datum_tmp.dptr); + } + } else { + if (delete) { + gdbm_delete(sessiondb, key_datum); + } + } + + free(key_datum.dptr); + entry.active = 1; + + data_datum.dptr = (char *) &entry; + data_datum.dsize = sizeof(ippool_info); + + if (old){ + strlcpy(old_key.nas, NASname, sizeof(old_key.nas)); + old_key.port = port; + key_datum.dptr = (char *) &old_key; + key_datum.dsize = sizeof(old_ippool_key); + printf("rlm_ippool_tool: Allocating ip to nas/port: %s/%u\n", old_key.nas, old_key.port); + } else { + memcpy(key.key, key_str, 16); + key_datum.dptr = (char *) &key; + key_datum.dsize = sizeof(ippool_key); + printf("rlm_ippool_tool: Allocating ip to key: '%s'\n", hex_str); + } + + rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE); + if (rcode < 0) { + printf("rlm_ippool_tool: Failed storing data to %s: %s\n", + sessiondbname, gdbm_strerror(gdbm_errno)); + goto close; + } + + /* Increase the ip index count */ + key_datum.dptr = (char *) &entry.ipaddr; + key_datum.dsize = sizeof(uint32_t); + data_datum = gdbm_fetch(indexdb, key_datum); + if (data_datum.dptr) { + memcpy(&num, data_datum.dptr, sizeof(int)); + } else { + num = 0; + } + + num++; + printf("rlm_ippool_tool: num: %d\n", num); + data_datum.dptr = (char *) # + data_datum.dsize = sizeof(int); + + rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE); + if (rcode < 0) { + printf("rlm_ippool_tool: Failed storing data to %s: %s\n", + indexdbname, gdbm_strerror(gdbm_errno)); + + goto close; + } + + if (old) { + printf("rlm_ippool_tool: Allocated ip %s to client on nas %s, port %u\n", + ipaddress, old_key.nas, port); + } else { + printf("rlm_ippool_tool: Allocated ip %s to key '%s'\n", ipaddress, hex_str); + } + } + + close: + gdbm_close(indexdb); + gdbm_close(sessiondb); +} + + +void tonewformat(char *sessiondbname, char *newsessiondbname) { + GDBM_FILE sessiondb; + GDBM_FILE newsessiondb; + datum key_datum, keynext_datum, data_datum, newkey_datum; + old_ippool_key old_key; + ippool_key key; + uint8_t key_str[17]; + char hex_str[35]; + int rcode; + + sessiondb = gdbm_open(sessiondbname, 512, GDBM_READER, 0,NULL); + newsessiondb = gdbm_open(newsessiondbname, 512, GDBM_NEWDB, 0,NULL); + + if (!sessiondb || !newsessiondb) return; + + memset(key_str, 0, 17); + + key_datum = gdbm_firstkey(sessiondb); + while (key_datum.dptr) { + keynext_datum = gdbm_nextkey(sessiondb, key_datum); + + if (key_datum.dsize != sizeof(struct old_ippool_key)) { + goto next; + } + + char md5_input_str[MAX_STRING_LEN]; + FR_MD5_CTX md5_context; + + memcpy(&old_key, key_datum.dptr, sizeof(struct old_ippool_key)); + + snprintf(md5_input_str, MAX_STRING_LEN, "%s %d", old_key.nas, old_key.port); + + fr_md5_init(&md5_context); + fr_md5_update(&md5_context, (uint8_t *) md5_input_str, strlen(md5_input_str)); + fr_md5_final(key_str, &md5_context); + + memcpy(key.key, key_str, 16); + fr_bin2hex(hex_str, key_str, 16); + hex_str[32] = '\0'; + + printf("rlm_ippool_tool: Transforming pair nas/port (%s/%d) to md5 '%s'\n", + old_key.nas, old_key.port, hex_str); + + newkey_datum.dptr = (char *) &key; + newkey_datum.dsize = sizeof(ippool_key); + data_datum = gdbm_fetch(sessiondb, key_datum); + + if (!data_datum.dptr) { + goto next; + } + + rcode = gdbm_store(newsessiondb, newkey_datum, data_datum, GDBM_REPLACE); + if (rcode < 0) { + printf("Failed to update new file %s: %s\n", newsessiondbname, gdbm_strerror(gdbm_errno)); + gdbm_close(newsessiondb); + gdbm_close(sessiondb); + return; + } + + next: + key_datum = keynext_datum; + } + + gdbm_close(newsessiondb); + gdbm_close(sessiondb); +} + +void viewdb(char *sessiondbname, char *indexdbname, char *ipaddress, int old) { + GDBM_FILE sessiondb; + GDBM_FILE indexdb; + datum key_datum, keynext_datum, data_datum, save_datum; + old_ippool_key old_key; + ippool_key key; + ippool_info info; + struct in_addr ipaddr; + int num; + uint8_t key_str[17]; + char hex_str[35]; + char *ip; + int mode = GDBM_READER; + int rcode; + + if (rflag) mode = GDBM_WRITER; + sessiondb = gdbm_open(sessiondbname, 512, mode, 0,NULL); + indexdb = gdbm_open(indexdbname, 512, mode, 0,NULL); + + if ((!sessiondb) || (!indexdb)) { + return; + } + + memset(&key, 0, sizeof(key)); /* -Winitialize */ + memset(key_str, 0,17); + + key_datum = gdbm_firstkey(sessiondb); + while (key_datum.dptr) { + keynext_datum = gdbm_nextkey(sessiondb, key_datum); + + if ((key_datum.dsize != sizeof(struct ippool_key)) && + (key_datum.dsize != sizeof(struct old_ippool_key))) { + goto next; + } + + if (old) { + memcpy(&old_key, key_datum.dptr, sizeof(struct old_ippool_key)); + } else { + memcpy(&key, key_datum.dptr, sizeof(struct ippool_key)); + } + + data_datum = gdbm_fetch(sessiondb, key_datum); + if (!data_datum.dptr) { + goto next; + } + + memcpy(&info, data_datum.dptr, sizeof(struct ippool_info)); + memcpy(&ipaddr, &info.ipaddr, 4); + ip = inet_ntoa(ipaddr); + + if (info.active) active++; + + if (vflag && MATCH_IP(ipaddress, ip) && MATCH_ACTIVE(info)) { + if (old) { + printf("NAS:%s port:0x%x - ", old_key.nas, old_key.port); + } else { + memcpy(key_str, key.key, 16); + fr_bin2hex(hex_str, key_str, 16); + hex_str[32] = '\0'; + printf("KEY: '%s' - ", hex_str); + } + } + + if (!vflag && aflag && info.active && MATCH_IP(ipaddress, ip)) { + printf("%s\n", ip); + } else if (vflag && MATCH_IP(ipaddress, ip) && MATCH_ACTIVE(info)) { + printf("ipaddr:%s active:%d cli:%s", + inet_ntoa(ipaddr), info.active, info.cli); + } + + /* + * algorythm copied from rlm_ippool.c: + * - set active to zero + * - set number of sessions to zero + */ + if (rflag && MATCH_IP(ipaddress, ip)) { + info.active = 0; + save_datum.dptr = key_datum.dptr; + save_datum.dsize = key_datum.dsize; + data_datum.dptr = (char *) &info; + data_datum.dsize = sizeof(ippool_info); + + rcode = gdbm_store(sessiondb, key_datum, data_datum, GDBM_REPLACE); + if (rcode < 0) { + printf("Failed to update %s: %s\n", ip, gdbm_strerror(gdbm_errno)); + gdbm_close(indexdb); + gdbm_close(sessiondb); + return; + } + + key_datum.dptr = (char *)&info.ipaddr; + key_datum.dsize = sizeof(uint32_t); + data_datum = gdbm_fetch(indexdb, key_datum); + + if (data_datum.dptr != NULL) { + memcpy(&num, data_datum.dptr, sizeof(int)); + if (num > 0) { + num--; + data_datum.dptr = (char *) # + data_datum.dsize = sizeof(int); + rcode = gdbm_store(indexdb, key_datum, data_datum, GDBM_REPLACE); + + if (rcode < 0) { + printf("Failed to update %s: %s\n", ip, gdbm_strerror(gdbm_errno)); + gdbm_close(indexdb); + gdbm_close(sessiondb); + return; + } + + if (num > 0 && info.extra == 1) { + gdbm_delete(sessiondb, save_datum); + } + } + } + } + + key_datum.dptr = (char *)&info.ipaddr; + key_datum.dsize = sizeof(uint32_t); + data_datum = gdbm_fetch(indexdb, key_datum); + + if (data_datum.dptr!= NULL) { + memcpy(&num, data_datum.dptr, sizeof(int)); + + if (vflag && MATCH_IP(ipaddress, ip) && MATCH_ACTIVE(info)) { + printf(" num:%d", num); + } + } + + if (vflag && MATCH_IP(ipaddress, ip) && MATCH_ACTIVE(info)) { + printf("\n"); + } else if (vflag && !ipaddress){ + if (old) { + printf("NAS:%s port:0x%x\n", old_key.nas, old_key.port); + } else { + memcpy(key_str, key.key, 16); + fr_bin2hex(hex_str, key_str, 16); + hex_str[32] = '\0'; + printf("KEY: '%s' - ", hex_str); + } + } + + next: + key_datum = keynext_datum; + } + + gdbm_close(indexdb); + gdbm_close(sessiondb); +} + +void NEVER_RETURNS usage(char *argv0) { + printf("Usage: %s [-a] [-c] [-o] [-v] [ipaddress]\n", argv0); + printf(" -a: print all active entries\n"); + printf(" -c: report number of active entries\n"); + printf(" -r: remove active entries\n"); + printf(" -v: verbose report of all entries\n"); + printf(" -o: Assume old database format (nas/port pair, not md5 output)\n"); + printf(" If an ipaddress is specified then that address is used to\n"); + printf(" limit the actions or output.\n"); + printf(" Usage: %s -n \n", argv0); + printf(" -n: Mark the entry nasIP/nasPort as having ipaddress\n"); + printf(" Usage: %s -u \n", argv0); + printf(" -u: Update old format database to new.\n"); + exit(0); +} + +int main(int argc, char **argv) { + int ch; + char *argv0 = argv[0]; + + while ((ch = getopt(argc, argv, "acrvnou"))!= -1) + switch (ch) { + case 'a': + aflag++; + break; + + case 'c': + cflag++; + break; + + case 'r': + rflag++; + break; + + case 'v': + vflag = 1; + break; + + case 'n': + nflag = 1; + break; + + case 'o': + oflag = 1; + break; + + case 'u': + uflag = 1; + break; + + default: + usage(argv0); + } + argc -= optind; + argv += optind; + + if ((argc == 2 || argc == 3) && !nflag && !uflag) { + viewdb(argv[0], argv[1], argv[2], oflag); + if (cflag) printf("%d\n", active); + } else { + if (argc == 5 && nflag) { + addip(argv[0], argv[1], argv[2], argv[3], argv[4], oflag); + } else if (argc == 2 && uflag) { + tonewformat(argv[0], argv[1]); + } else { + usage(argv0); + } + } + + return 0; +} -- cgit v1.2.3