18ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project/*
28ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
38ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* radrealms.c
48ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
58ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* A pppd plugin which is stacked on top of radius.so.  This plugin
68ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* allows selection of alternate set of servers based on the user's realm.
78ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
88ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Author: Ben McKeegan  ben@netservers.co.uk
98ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* Copyright (C) 2002 Netservers
118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* This plugin may be distributed according to the terms of the GNU
138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project* General Public License, version 2 or (at your option) any later version.
148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*
158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project*/
168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic char const RCSID[] =
188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    "$Id: radrealms.c,v 1.2 2004/11/14 07:26:26 paulus Exp $";
198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "pppd.h"
218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include "radiusclient.h"
228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <stdio.h>
238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <string.h>
248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project#include <stdlib.h>
258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchar pppd_version[] = VERSION;
278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectchar radrealms_config[MAXPATHLEN] = "/etc/radiusclient/realms";
298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic option_t Options[] = {
318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    { "realms-config-file", o_string, &radrealms_config },
328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    { NULL }
338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project};
348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectextern void (*radius_pre_auth_hook)(char const *user,
368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project				    SERVER **authserver,
378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project				    SERVER **acctserver);
388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectstatic void
408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectlookup_realm(char const *user,
418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	     SERVER **authserver,
428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	     SERVER **acctserver)
438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    char *realm;
458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    FILE *fd;
468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    SERVER *accts, *auths, *s;
478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    char buffer[512], *p;
488ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    int line = 0;
498ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
508ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    auths = (SERVER *) malloc(sizeof(SERVER));
518ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    auths->max = 0;
528ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    accts = (SERVER *) malloc(sizeof(SERVER));
538ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    accts->max = 0;
548ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
558ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    realm = strrchr(user, '@');
568ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
578ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (realm) {
588ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	info("Looking up servers for realm '%s'", realm);
598ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    } else {
608ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	info("Looking up servers for DEFAULT realm");
618ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
628ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (realm) {
638ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (*(++realm) == '\0') {
648ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    realm = NULL;
658ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
668ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
678ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
688ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if ((fd = fopen(radrealms_config, "r")) == NULL) {
698ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	option_error("cannot open %s", radrealms_config);
708ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	return;
718ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
728ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    info("Reading %s", radrealms_config);
738ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
748ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    while ((fgets(buffer, sizeof(buffer), fd) != NULL)) {
758ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	line++;
768ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
778ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((*buffer == '\n') || (*buffer == '#') || (*buffer == '\0'))
788ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    continue;
798ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
808ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	buffer[strlen(buffer)-1] = '\0';
818ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
828ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	p = strtok(buffer, "\t ");
838ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
848ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (p == NULL || (strcmp(p, "authserver") !=0
858ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    && strcmp(p, "acctserver"))) {
868ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    fclose(fd);
878ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    option_error("%s: invalid line %d: %s", radrealms_config,
888ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			 line, buffer);
898ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    return;
908ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
918ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	info("Parsing '%s' entry:", p);
928ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	s = auths;
938ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (p[1] == 'c') {
948ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    s = accts;
958ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
968ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if (s->max >= SERVER_MAX)
978ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    continue;
988ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
998ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((p = strtok(NULL, "\t ")) == NULL) {
1008ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    fclose(fd);
1018ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    option_error("%s: realm name missing on line %d: %s",
1028ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			 radrealms_config, line, buffer);
1038ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    return;
1048ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	}
1058ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1068ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	if ((realm != NULL && strcmp(p, realm) == 0) ||
1078ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    (realm == NULL && strcmp(p, "DEFAULT") == 0) ) {
1088ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    info(" - Matched realm %s", p);
1098ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if ((p = strtok(NULL, ":")) == NULL) {
1108ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		fclose(fd);
1118ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		option_error("%s: server address missing on line %d: %s",
1128ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			     radrealms_config, line, buffer);
1138ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
1148ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
1158ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    s->name[s->max] = strdup(p);
1168ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    info(" - Address is '%s'",p);
1178ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    if ((p = strtok(NULL, "\t ")) == NULL) {
1188ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		fclose(fd);
1198ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		option_error("%s: server port missing on line %d:  %s",
1208ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project			     radrealms_config, line, buffer);
1218ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project		return;
1228ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    }
1238ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    s->port[s->max] = atoi(p);
1248ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    info(" - Port is '%d'", s->port[s->max]);
1258ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    s->max++;
1268ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	} else
1278ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	    info(" - Skipping realm '%s'", p);
1288ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    }
1298ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    fclose(fd);
1308ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1318ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (accts->max)
1328ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	*acctserver = accts;
1338ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1348ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    if (auths->max)
1358ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project	*authserver = auths;
1368ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1378ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    return;
1388ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
1398ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1408ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectvoid
1418ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Projectplugin_init(void)
1428ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project{
1438ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    radius_pre_auth_hook = lookup_realm;
1448ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project
1458ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    add_options(Options);
1468ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project    info("RADIUS Realms plugin initialized.");
1478ad0dd2a5c5f23cd210aedba72a43e48026e7436The Android Open Source Project}
148