Home | History | Annotate | Download | only in radius
      1 /*
      2 *
      3 * radrealms.c
      4 *
      5 * A pppd plugin which is stacked on top of radius.so.  This plugin
      6 * allows selection of alternate set of servers based on the user's realm.
      7 *
      8 * Author: Ben McKeegan  ben (at) netservers.co.uk
      9 *
     10 * Copyright (C) 2002 Netservers
     11 *
     12 * This plugin may be distributed according to the terms of the GNU
     13 * General Public License, version 2 or (at your option) any later version.
     14 *
     15 */
     16 
     17 static char const RCSID[] =
     18     "$Id: radrealms.c,v 1.2 2004/11/14 07:26:26 paulus Exp $";
     19 
     20 #include "pppd.h"
     21 #include "radiusclient.h"
     22 #include <stdio.h>
     23 #include <string.h>
     24 #include <stdlib.h>
     25 
     26 char pppd_version[] = VERSION;
     27 
     28 char radrealms_config[MAXPATHLEN] = "/etc/radiusclient/realms";
     29 
     30 static option_t Options[] = {
     31     { "realms-config-file", o_string, &radrealms_config,
     32       "Configuration file for RADIUS realms", OPT_STATIC, NULL, MAXPATHLEN },
     33     { NULL }
     34 };
     35 
     36 extern void (*radius_pre_auth_hook)(char const *user,
     37 				    SERVER **authserver,
     38 				    SERVER **acctserver);
     39 
     40 static void
     41 lookup_realm(char const *user,
     42 	     SERVER **authserver,
     43 	     SERVER **acctserver)
     44 {
     45     char *realm;
     46     FILE *fd;
     47     SERVER *accts, *auths, *s;
     48     char buffer[512], *p;
     49     int line = 0;
     50 
     51     auths = (SERVER *) malloc(sizeof(SERVER));
     52     auths->max = 0;
     53     accts = (SERVER *) malloc(sizeof(SERVER));
     54     accts->max = 0;
     55 
     56     realm = strrchr(user, '@');
     57 
     58     if (realm) {
     59 	info("Looking up servers for realm '%s'", realm);
     60     } else {
     61 	info("Looking up servers for DEFAULT realm");
     62     }
     63     if (realm) {
     64 	if (*(++realm) == '\0') {
     65 	    realm = NULL;
     66 	}
     67     }
     68 
     69     if ((fd = fopen(radrealms_config, "r")) == NULL) {
     70 	option_error("cannot open %s", radrealms_config);
     71 	return;
     72     }
     73     info("Reading %s", radrealms_config);
     74 
     75     while ((fgets(buffer, sizeof(buffer), fd) != NULL)) {
     76 	line++;
     77 
     78 	if ((*buffer == '\n') || (*buffer == '#') || (*buffer == '\0'))
     79 	    continue;
     80 
     81 	buffer[strlen(buffer)-1] = '\0';
     82 
     83 	p = strtok(buffer, "\t ");
     84 
     85 	if (p == NULL || (strcmp(p, "authserver") !=0
     86 	    && strcmp(p, "acctserver"))) {
     87 	    fclose(fd);
     88 	    option_error("%s: invalid line %d: %s", radrealms_config,
     89 			 line, buffer);
     90 	    return;
     91 	}
     92 	info("Parsing '%s' entry:", p);
     93 	s = auths;
     94 	if (p[1] == 'c') {
     95 	    s = accts;
     96 	}
     97 	if (s->max >= SERVER_MAX)
     98 	    continue;
     99 
    100 	if ((p = strtok(NULL, "\t ")) == NULL) {
    101 	    fclose(fd);
    102 	    option_error("%s: realm name missing on line %d: %s",
    103 			 radrealms_config, line, buffer);
    104 	    return;
    105 	}
    106 
    107 	if ((realm != NULL && strcmp(p, realm) == 0) ||
    108 	    (realm == NULL && strcmp(p, "DEFAULT") == 0) ) {
    109 	    info(" - Matched realm %s", p);
    110 	    if ((p = strtok(NULL, ":")) == NULL) {
    111 		fclose(fd);
    112 		option_error("%s: server address missing on line %d: %s",
    113 			     radrealms_config, line, buffer);
    114 		return;
    115 	    }
    116 	    s->name[s->max] = strdup(p);
    117 	    info(" - Address is '%s'",p);
    118 	    if ((p = strtok(NULL, "\t ")) == NULL) {
    119 		fclose(fd);
    120 		option_error("%s: server port missing on line %d:  %s",
    121 			     radrealms_config, line, buffer);
    122 		return;
    123 	    }
    124 	    s->port[s->max] = atoi(p);
    125 	    info(" - Port is '%d'", s->port[s->max]);
    126 	    s->max++;
    127 	} else
    128 	    info(" - Skipping realm '%s'", p);
    129     }
    130     fclose(fd);
    131 
    132     if (accts->max)
    133 	*acctserver = accts;
    134 
    135     if (auths->max)
    136 	*authserver = auths;
    137 
    138     return;
    139 }
    140 
    141 void
    142 plugin_init(void)
    143 {
    144     radius_pre_auth_hook = lookup_realm;
    145 
    146     add_options(Options);
    147     info("RADIUS Realms plugin initialized.");
    148 }
    149