summaryrefslogtreecommitdiff
path: root/pppd/plugins/radius/radrealms.c
blob: 7a30370121bdbca99fab7ac7b7479b74933d3d6b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
*
* radrealms.c
*
* A pppd plugin which is stacked on top of radius.so.  This plugin
* allows selection of alternate set of servers based on the user's realm.
*
* Author: Ben McKeegan  ben@netservers.co.uk
*
* Copyright (C) 2002 Netservers
*
* This plugin may be distributed according to the terms of the GNU
* General Public License, version 2 or (at your option) any later version.
*
*/

static char const RCSID[] =
    "$Id: radrealms.c,v 1.2 2004/11/14 07:26:26 paulus Exp $";

#include "pppd.h"
#include "radiusclient.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char pppd_version[] = VERSION;

char radrealms_config[MAXPATHLEN] = "/etc/radiusclient/realms";

static option_t Options[] = {
    { "realms-config-file", o_string, &radrealms_config,
      "Configuration file for RADIUS realms", OPT_STATIC, NULL, MAXPATHLEN },
    { NULL }
};

extern void (*radius_pre_auth_hook)(char const *user,
				    SERVER **authserver,
				    SERVER **acctserver);

static void
lookup_realm(char const *user,
	     SERVER **authserver,
	     SERVER **acctserver)
{
    char *realm;
    FILE *fd;
    SERVER *accts, *auths, *s;
    char buffer[512], *p;
    int line = 0;
    
    auths = (SERVER *) malloc(sizeof(SERVER));
    auths->max = 0;
    accts = (SERVER *) malloc(sizeof(SERVER));
    accts->max = 0;
    
    realm = strrchr(user, '@');
    
    if (realm) {
	info("Looking up servers for realm '%s'", realm);
    } else {
	info("Looking up servers for DEFAULT realm");
    }
    if (realm) {
	if (*(++realm) == '\0') {
	    realm = NULL;
	}
    }
    
    if ((fd = fopen(radrealms_config, "r")) == NULL) {
	option_error("cannot open %s", radrealms_config);
	return;
    } 
    info("Reading %s", radrealms_config);
    
    while ((fgets(buffer, sizeof(buffer), fd) != NULL)) {
	line++;

	if ((*buffer == '\n') || (*buffer == '#') || (*buffer == '\0'))
	    continue;

	buffer[strlen(buffer)-1] = '\0';

	p = strtok(buffer, "\t ");

	if (p == NULL || (strcmp(p, "authserver") !=0
	    && strcmp(p, "acctserver"))) {
	    fclose(fd);
	    option_error("%s: invalid line %d: %s", radrealms_config,
			 line, buffer);
	    return;
	}
	info("Parsing '%s' entry:", p);
	s = auths;
	if (p[1] == 'c') {
	    s = accts;
	}
	if (s->max >= SERVER_MAX)
	    continue;

	if ((p = strtok(NULL, "\t ")) == NULL) {
	    fclose(fd);
	    option_error("%s: realm name missing on line %d: %s",
			 radrealms_config, line, buffer);
	    return;
	}

	if ((realm != NULL && strcmp(p, realm) == 0) ||
	    (realm == NULL && strcmp(p, "DEFAULT") == 0) ) {
	    info(" - Matched realm %s", p);
	    if ((p = strtok(NULL, ":")) == NULL) {
		fclose(fd);
		option_error("%s: server address missing on line %d: %s",
			     radrealms_config, line, buffer);
		return;
	    }
	    s->name[s->max] = strdup(p);
	    info(" - Address is '%s'",p);
	    if ((p = strtok(NULL, "\t ")) == NULL) {
		fclose(fd);
		option_error("%s: server port missing on line %d:  %s",
			     radrealms_config, line, buffer);
		return;
	    }
	    s->port[s->max] = atoi(p);
	    info(" - Port is '%d'", s->port[s->max]);
	    s->max++;
	} else 
	    info(" - Skipping realm '%s'", p);
    }
    fclose(fd);

    if (accts->max)
	*acctserver = accts;

    if (auths->max)
	*authserver = auths;

    return;
}

void
plugin_init(void)
{
    radius_pre_auth_hook = lookup_realm;

    add_options(Options);
    info("RADIUS Realms plugin initialized.");
}