summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKozlov Dmitry <dima@server>2010-09-04 16:20:11 +0400
committerKozlov Dmitry <dima@server>2010-09-04 16:20:11 +0400
commitaf5a96e2d04056b065a36ecbd140a16d0685c7e6 (patch)
treef873b3c5c68a72d2df1785fdd0931bc57c91fd35
parente8aa3a1457295f70f8ccc9cd7f2f9073f01a5e2e (diff)
downloadaccel-ppp-af5a96e2d04056b065a36ecbd140a16d0685c7e6.tar.gz
accel-ppp-af5a96e2d04056b065a36ecbd140a16d0685c7e6.zip
started work on radius module
-rw-r--r--accel-pptpd/CMakeLists.txt2
-rw-r--r--accel-pptpd/accel-pptpd.conf4
-rw-r--r--accel-pptpd/ppp/ppp.c5
-rw-r--r--accel-pptpd/ppp/ppp.h30
-rw-r--r--accel-pptpd/ppp/ppp_notify.c34
-rw-r--r--accel-pptpd/ppp/ppp_pd.c12
-rw-r--r--accel-pptpd/pwdb.c67
-rw-r--r--accel-pptpd/pwdb.h23
-rw-r--r--accel-pptpd/radius/CMakeLists.txt8
-rw-r--r--accel-pptpd/radius/dict.c219
-rw-r--r--accel-pptpd/radius/dictionary240
-rw-r--r--accel-pptpd/radius/radius.c74
-rw-r--r--accel-pptpd/radius/radius.h28
13 files changed, 729 insertions, 17 deletions
diff --git a/accel-pptpd/CMakeLists.txt b/accel-pptpd/CMakeLists.txt
index 64f351fa..041c6681 100644
--- a/accel-pptpd/CMakeLists.txt
+++ b/accel-pptpd/CMakeLists.txt
@@ -8,6 +8,7 @@ INCLUDE_DIRECTORIES(include)
ADD_SUBDIRECTORY(triton)
ADD_SUBDIRECTORY(ctrl)
ADD_SUBDIRECTORY(auth)
+ADD_SUBDIRECTORY(radius)
ADD_EXECUTABLE(pptpd
ppp/ppp.c
@@ -22,6 +23,7 @@ ADD_EXECUTABLE(pptpd
ppp/ipcp_opt_ipaddr.c
ppp/ipcp_opt_dns.c
ppp/ppp_ccp.c
+ ppp/ppp_notify.c
log.c
pwdb.c
diff --git a/accel-pptpd/accel-pptpd.conf b/accel-pptpd/accel-pptpd.conf
index fa2f128c..9b635340 100644
--- a/accel-pptpd/accel-pptpd.conf
+++ b/accel-pptpd/accel-pptpd.conf
@@ -1,6 +1,7 @@
[modules]
./libpptp.so
./libauth_mschap_v2.so
+./libradius.so
[core]
log-error=/dev/stderr
@@ -11,3 +12,6 @@ echo-failure=3
[pptp]
echo-interval=3
+
+[radius]
+dictionary=dictionary
diff --git a/accel-pptpd/ppp/ppp.c b/accel-pptpd/ppp/ppp.c
index 5c2eb910..4ad8221b 100644
--- a/accel-pptpd/ppp/ppp.c
+++ b/accel-pptpd/ppp/ppp.c
@@ -18,6 +18,7 @@
#include "log.h"
static LIST_HEAD(layers);
+int sock_fd;
struct layer_node_t
{
@@ -94,6 +95,7 @@ int __export establish_ppp(struct ppp_t *ppp)
INIT_LIST_HEAD(&ppp->chan_handlers);
INIT_LIST_HEAD(&ppp->unit_handlers);
+ INIT_LIST_HEAD(&ppp->pd_list);
init_layers(ppp);
@@ -127,6 +129,7 @@ int __export establish_ppp(struct ppp_t *ppp)
log_debug("ppp established\n");
+ ppp_notify_started(ppp);
start_first_layer(ppp);
return 0;
@@ -159,6 +162,7 @@ static void destablish_ppp(struct ppp_t *ppp)
log_debug("ppp destablished\n");
+ ppp_notify_finished(ppp);
ppp->ctrl->finished(ppp);
}
@@ -481,7 +485,6 @@ struct ppp_layer_data_t *ppp_find_layer_data(struct ppp_t *ppp, struct ppp_layer
return NULL;
}
-int sock_fd;
static void __init ppp_init(void)
{
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
diff --git a/accel-pptpd/ppp/ppp.h b/accel-pptpd/ppp/ppp.h
index d880fc2a..da2fb97c 100644
--- a/accel-pptpd/ppp/ppp.h
+++ b/accel-pptpd/ppp/ppp.h
@@ -12,13 +12,6 @@
#define PPP_HEADERLEN 4
#define PPP_MTU 1500
-/*
- * Timeouts.
- */
-#define DEFTIMEOUT 3 /* Timeout time in seconds */
-#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */
-#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */
-#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */
/*
* Protocol field values.
@@ -48,8 +41,6 @@
#define PPP_LAYER_CCP 3
#define PPP_LAYER_IPCP 4
-#define AUTH_MAX 3
-
struct ppp_t;
struct ppp_ctrl_t
@@ -59,6 +50,20 @@ struct ppp_ctrl_t
void (*finished)(struct ppp_t*);
};
+struct ppp_notified_t
+{
+ struct list_head entry;
+ void (*started)(struct ppp_notified_t *, struct ppp_t *);
+ void (*finished)(struct ppp_notified_t *, struct ppp_t *);
+ void (*authenticated)(struct ppp_notified_t *, struct ppp_t *);
+};
+
+struct ppp_pd_t
+{
+ struct list_head entry;
+ void *key;
+};
+
struct ppp_t
{
struct triton_md_handler_t chan_hnd;
@@ -87,6 +92,8 @@ struct ppp_t
struct list_head layers;
struct ppp_lcp_t *lcp;
+
+ struct list_head pd_list;
};
struct ppp_layer_t;
@@ -134,5 +141,10 @@ int ppp_register_layer(const char *name, struct ppp_layer_t *);
void ppp_unregister_layer(struct ppp_layer_t *);
struct ppp_layer_data_t *ppp_find_layer_data(struct ppp_t *, struct ppp_layer_t *);
+void ppp_register_notified(struct ppp_notified_t *);
+void ppp_unregister_notified(struct ppp_notified_t *);
+void ppp_notify_started(struct ppp_t *ppp);
+void ppp_notify_finished(struct ppp_t *ppp);
+
extern int sock_fd; // internet socket for ioctls
#endif
diff --git a/accel-pptpd/ppp/ppp_notify.c b/accel-pptpd/ppp/ppp_notify.c
new file mode 100644
index 00000000..94ceb6d2
--- /dev/null
+++ b/accel-pptpd/ppp/ppp_notify.c
@@ -0,0 +1,34 @@
+#include "ppp.h"
+
+static LIST_HEAD(notified_list);
+
+void __export ppp_register_notified(struct ppp_notified_t *n)
+{
+ list_add_tail(&n->entry, &notified_list);
+}
+
+void __export ppp_unregister_notified(struct ppp_notified_t *n)
+{
+ list_del(&n->entry);
+}
+
+void ppp_notify_started(struct ppp_t *ppp)
+{
+ struct ppp_notified_t *n;
+
+ list_for_each_entry(n, &notified_list, entry) {
+ if (n->started)
+ n->started(n, ppp);
+ }
+}
+
+void ppp_notify_finished(struct ppp_t *ppp)
+{
+ struct ppp_notified_t *n;
+
+ list_for_each_entry(n, &notified_list, entry) {
+ if (n->finished)
+ n->finished(n, ppp);
+ }
+}
+
diff --git a/accel-pptpd/ppp/ppp_pd.c b/accel-pptpd/ppp/ppp_pd.c
new file mode 100644
index 00000000..fe51bc01
--- /dev/null
+++ b/accel-pptpd/ppp/ppp_pd.c
@@ -0,0 +1,12 @@
+#include "ppp.h"
+
+int ppp_store_pd(struct ppp_t *ppp, pd_key_t key, void *data)
+{
+ struct ppp_pd_t *pd;
+
+ list_for_each_entry(pd, &ppp->pd_list, entry)
+ if (pd->key == key)
+ return -1;
+
+
+}
diff --git a/accel-pptpd/pwdb.c b/accel-pptpd/pwdb.c
index 37dd0c5f..8bde8fff 100644
--- a/accel-pptpd/pwdb.c
+++ b/accel-pptpd/pwdb.c
@@ -1,12 +1,69 @@
+#include <stdlib.h>
+
+#include "triton.h"
+
#include "pwdb.h"
-#include "ppp.h"
-__export int pwdb_check(struct ppp_t *ppp,const char *username,const char *password)
+static LIST_HEAD(pwdb_handlers);
+
+int __export pwdb_cleartext_check(struct ppp_t *ppp, const char *username,const char *password)
+{
+ struct pwdb_t *pwdb;
+ int r = PWDB_NO_IMPL;
+
+ list_for_each_entry(pwdb, &pwdb_handlers, entry) {
+ if (!pwdb->cleartext_check)
+ continue;
+ r = pwdb->cleartext_check(pwdb, ppp, username, password);
+ if (r == PWDB_NO_IMPL)
+ continue;
+ break;
+ }
+
+ return r;
+}
+int __export pwdb_encrypted_check(struct ppp_t *ppp, const char *username, int type, ...)
+{
+ struct pwdb_t *pwdb;
+ int r = PWDB_NO_IMPL;
+ va_list args;
+
+ va_start(args, type);
+
+ list_for_each_entry(pwdb, &pwdb_handlers, entry) {
+ if (!pwdb->encrypted_check)
+ continue;
+ r = pwdb->encrypted_check(pwdb, ppp, username, type, args);
+ if (r == PWDB_NO_IMPL)
+ continue;
+ break;
+ }
+
+ return r;
+
+}
+__export const char *pwdb_get_passwd(struct ppp_t *ppp, const char *username)
{
- return 0;
+ struct pwdb_t *pwdb;
+ const char *r = NULL;
+
+ list_for_each_entry(pwdb, &pwdb_handlers, entry) {
+ if (!pwdb->get_passwd)
+ continue;
+ r = pwdb->get_passwd(pwdb, ppp, username);
+ if (r)
+ break;
+ }
+
+ return r;
}
-__export char *pwdb_get_passwd(struct ppp_t *ppp, const char *username)
+void __export pwdb_register(struct pwdb_t *pwdb)
+{
+ list_add_tail(&pwdb->entry, &pwdb_handlers);
+}
+void __export pwdb_unregister(struct pwdb_t *pwdb)
{
- return strdup("test");
+ list_del(&pwdb->entry);
}
+
diff --git a/accel-pptpd/pwdb.h b/accel-pptpd/pwdb.h
index 07c45b09..42f9133c 100644
--- a/accel-pptpd/pwdb.h
+++ b/accel-pptpd/pwdb.h
@@ -1,10 +1,29 @@
#ifndef PWDB_H
#define PWDB_H
+#include <stdarg.h>
+#include "list.h"
+
struct ppp_t;
-int pwdb_check(struct ppp_t*,const char *username,const char *password);
-char *pwdb_get_passwd(struct ppp_t*, const char *username);
+#define PWDB_SUCCESS 0
+#define PWDB_DENIED 1
+#define PWDB_NO_IMPL 2
+
+struct pwdb_t
+{
+ struct list_head entry;
+ int (*cleartext_check)(struct pwdb_t *, struct ppp_t *, const char *username, const char *password);
+ int (*encrypted_check)(struct pwdb_t *, struct ppp_t *, const char *username, int type, va_list args);
+ const char* (*get_passwd)(struct pwdb_t *, struct ppp_t *, const char *username);
+};
+
+int pwdb_cleartext_check(struct ppp_t *, const char *username,const char *password);
+int pwdb_encrypted_check(struct ppp_t *, const char *username, int type, ...);
+const char *pwdb_get_passwd(struct ppp_t *, const char *username);
+
+void pwdb_register(struct pwdb_t *);
+void pwdb_unregister(struct pwdb_t *);
#endif
diff --git a/accel-pptpd/radius/CMakeLists.txt b/accel-pptpd/radius/CMakeLists.txt
new file mode 100644
index 00000000..a53491f6
--- /dev/null
+++ b/accel-pptpd/radius/CMakeLists.txt
@@ -0,0 +1,8 @@
+SET(target radius)
+SET(sources
+ radius.c
+ dict.c
+)
+
+ADD_LIBRARY(radius SHARED ${sources})
+
diff --git a/accel-pptpd/radius/dict.c b/accel-pptpd/radius/dict.c
new file mode 100644
index 00000000..62a25cfd
--- /dev/null
+++ b/accel-pptpd/radius/dict.c
@@ -0,0 +1,219 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "list.h"
+#include "radius.h"
+#include "log.h"
+
+
+struct dict_value_t
+{
+ struct list_head entry;
+ rad_value_t val;
+ const char *name;
+};
+
+struct dict_attr_t
+{
+ struct list_head entry;
+ const char *name;
+ int id;
+ int type;
+ rad_value_t val;
+ struct list_head values;
+};
+
+static char *skip_word(char *ptr)
+{
+ for(; *ptr; ptr++)
+ if (*ptr == ' ' || *ptr == '\t' || *ptr == '\n')
+ break;
+ return ptr;
+}
+static char *skip_space(char *ptr)
+{
+ for(; *ptr; ptr++)
+ if (*ptr != ' ' && *ptr != '\t')
+ break;
+ return ptr;
+}
+static int split(char *buf, char **ptr)
+{
+ int i;
+
+ for (i = 0; i < 3; i++) {
+ buf = skip_word(buf);
+ if (!*buf)
+ return -1;
+
+ *buf = 0;
+
+ buf = skip_space(buf + 1);
+ if (!*buf)
+ return -1;
+
+ ptr[i] = buf;
+ }
+
+ buf = skip_word(buf);
+ if (*buf == '\n')
+ *buf = 0;
+ else if (*buf)
+ return -1;
+
+ return 0;
+}
+
+struct dict_attr_t *find_attr(struct rad_dict_t *dict, const char *name)
+{
+ struct dict_attr_t *attr;
+
+ list_for_each_entry(attr, &dict->items, entry)
+ if (!strcmp(attr->name, name))
+ return attr;
+
+ return NULL;
+}
+
+#define BUF_SIZE 1024
+void *rad_load_dict(const char *fname)
+{
+ FILE *f;
+ char *buf, *ptr[3], *endptr;
+ int n = 0;
+ struct rad_dict_t *dict;
+ struct dict_attr_t *attr;
+ struct dict_value_t *val;
+
+ f = fopen(fname, "r");
+ if (!f) {
+ log_error("radius: open dictioanary '%s': %s\n", fname, strerror(errno));
+ return NULL;
+ }
+
+ buf = malloc(BUF_SIZE);
+ if (!buf) {
+ log_error("radius: out of memory\n");
+ fclose(f);
+ return NULL;
+ }
+
+ dict = malloc(sizeof(*dict));
+ if (!dict) {
+ log_error("radius: out of memory\n");
+ fclose(f);
+ free(buf);
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&dict->items);
+
+ while (fgets(buf, BUF_SIZE, f)) {
+ n++;
+ if (buf[0] == '#' || buf[0] == '\n' || buf[0] == 0)
+ continue;
+ if (split(buf, ptr)) {
+ log_error("radius:%s:%i: syntaxis error\n", fname, n);
+ goto out_err;
+ }
+ if (!strcmp(buf, "ATTRIBUTE")) {
+ attr = malloc(sizeof(*attr));
+ if (!attr) {
+ log_error("radius: out of memory\n");
+ goto out_err;
+ }
+ memset(attr, 0, sizeof(*attr));
+ INIT_LIST_HEAD(&attr->values);
+ list_add_tail(&attr->entry, &dict->items);
+ attr->name = strdup(ptr[0]);
+ attr->id = strtol(ptr[1], &endptr, 10);
+ if (*endptr != 0) {
+ log_error("radius:%s:%i: syntaxis error\n", fname, n);
+ goto out_err;
+ }
+ if (!strcmp(ptr[2], "integer"))
+ attr->type = ATTR_TYPE_INTEGER;
+ else if (!strcmp(ptr[2], "string"))
+ attr->type = ATTR_TYPE_STRING;
+ else if (!strcmp(ptr[2], "date"))
+ attr->type = ATTR_TYPE_DATE;
+ else if (!strcmp(ptr[2], "ipaddr"))
+ attr->type = ATTR_TYPE_IPADDR;
+ else {
+ log_error("radius:%s:%i: unknown attribute type\n", fname, n);
+ goto out_err;
+ }
+ } else if (!strcmp(buf, "VALUE")) {
+ attr = find_attr(dict, ptr[0]);
+ if (!attr) {
+ log_error("radius:%s:%i: unknown attribute\n", fname, n);
+ goto out_err;
+ }
+ val = malloc(sizeof(*val));
+ if (!val) {
+ log_error("radius: out of memory\n");
+ goto out_err;
+ }
+ memset(val, 0, sizeof(*val));
+ list_add_tail(&val->entry, &attr->values);
+ val->name = strdup(ptr[1]);
+ switch (attr->type) {
+ case ATTR_TYPE_INTEGER:
+ val->val.integer = strtol(ptr[2], &endptr, 10);
+ if (*endptr != 0) {
+ log_error("radius:%s:%i: syntaxis error\n", fname, n);
+ goto out_err;
+ }
+ break;
+ case ATTR_TYPE_STRING:
+ val->val.string = strdup(ptr[2]);
+ break;
+ case ATTR_TYPE_DATE:
+ log_warn("radius:%s:%i: VALUE of type 'date' is not implemented yet\n", fname, n);
+ break;
+ case ATTR_TYPE_IPADDR:
+ log_warn("radius:%s:%i: VALUE of type 'ipaddr' is not implemented yet\n", fname, n);
+ break;
+ }
+ } else {
+ log_error("radius:%s:%i: syntaxis error\n");
+ goto out_err;
+ }
+ }
+
+ free(buf);
+ fclose(f);
+
+ return dict;
+
+out_err:
+ rad_free_dict(dict);
+ free(buf);
+ fclose(f);
+ return NULL;
+}
+
+void rad_free_dict(struct rad_dict_t *dict)
+{
+ struct dict_attr_t *attr;
+ struct dict_value_t *val;
+
+ while (!list_empty(&dict->items)) {
+ attr = list_entry(dict->items.next, typeof(*attr), entry);
+ while (!list_empty(&attr->values)) {
+ val = list_entry(attr->values.next, typeof(*val), entry);
+ list_del(&val->entry);
+ free((char*)val->name);
+ if (attr->type == ATTR_TYPE_STRING)
+ free((char*)val->val.string);
+ free(val);
+ }
+ list_del(&attr->entry);
+ free((char*)attr->name);
+ free(attr);
+ }
+ free(dict);
+}
+
diff --git a/accel-pptpd/radius/dictionary b/accel-pptpd/radius/dictionary
new file mode 100644
index 00000000..caebe9d7
--- /dev/null
+++ b/accel-pptpd/radius/dictionary
@@ -0,0 +1,240 @@
+#
+# Updated 97/06/13 to livingston-radius-2.01 miquels@cistron.nl
+#
+# This file contains dictionary translations for parsing
+# requests and generating responses. All transactions are
+# composed of Attribute/Value Pairs. The value of each attribute
+# is specified as one of 4 data types. Valid data types are:
+#
+# string - 0-253 octets
+# ipaddr - 4 octets in network byte order
+# integer - 32 bit value in big endian order (high byte first)
+# date - 32 bit value in big endian order - seconds since
+# 00:00:00 GMT, Jan. 1, 1970
+#
+# Enumerated values are stored in the user file with dictionary
+# VALUE translations for easy administration.
+#
+# Example:
+#
+# ATTRIBUTE VALUE
+# --------------- -----
+# Framed-Protocol = PPP
+# 7 = 1 (integer encoding)
+#
+
+#
+# Following are the proper new names. Use these.
+#
+ATTRIBUTE User-Name 1 string
+ATTRIBUTE Password 2 string
+ATTRIBUTE CHAP-Password 3 string
+ATTRIBUTE NAS-IP-Address 4 ipaddr
+ATTRIBUTE NAS-Port-Id 5 integer
+ATTRIBUTE Service-Type 6 integer
+ATTRIBUTE Framed-Protocol 7 integer
+ATTRIBUTE Framed-IP-Address 8 ipaddr
+ATTRIBUTE Framed-IP-Netmask 9 ipaddr
+ATTRIBUTE Framed-Routing 10 integer
+ATTRIBUTE Filter-Id 11 string
+ATTRIBUTE Framed-MTU 12 integer
+ATTRIBUTE Framed-Compression 13 integer
+ATTRIBUTE Login-IP-Host 14 ipaddr
+ATTRIBUTE Login-Service 15 integer
+ATTRIBUTE Login-TCP-Port 16 integer
+ATTRIBUTE Reply-Message 18 string
+ATTRIBUTE Callback-Number 19 string
+ATTRIBUTE Callback-Id 20 string
+ATTRIBUTE Framed-Route 22 string
+ATTRIBUTE Framed-IPX-Network 23 ipaddr
+ATTRIBUTE State 24 string
+ATTRIBUTE Class 25 string
+ATTRIBUTE Vendor-Specific 26 string
+ATTRIBUTE Session-Timeout 27 integer
+ATTRIBUTE Idle-Timeout 28 integer
+ATTRIBUTE Termination-Action 29 integer
+ATTRIBUTE Called-Station-Id 30 string
+ATTRIBUTE Calling-Station-Id 31 string
+ATTRIBUTE NAS-Identifier 32 string
+ATTRIBUTE Proxy-State 33 string
+ATTRIBUTE Login-LAT-Service 34 string
+ATTRIBUTE Login-LAT-Node 35 string
+ATTRIBUTE Login-LAT-Group 36 string
+ATTRIBUTE Framed-AppleTalk-Link 37 integer
+ATTRIBUTE Framed-AppleTalk-Network 38 integer
+ATTRIBUTE Framed-AppleTalk-Zone 39 string
+ATTRIBUTE Acct-Status-Type 40 integer
+ATTRIBUTE Acct-Delay-Time 41 integer
+ATTRIBUTE Acct-Input-Octets 42 integer
+ATTRIBUTE Acct-Output-Octets 43 integer
+ATTRIBUTE Acct-Session-Id 44 string
+ATTRIBUTE Acct-Authentic 45 integer
+ATTRIBUTE Acct-Session-Time 46 integer
+ATTRIBUTE Acct-Input-Packets 47 integer
+ATTRIBUTE Acct-Output-Packets 48 integer
+ATTRIBUTE Acct-Terminate-Cause 49 integer
+ATTRIBUTE Acct-Multi-Session-Id 50 string
+ATTRIBUTE Acct-Link-Count 51 integer
+ATTRIBUTE Event-Timestamp 55 integer
+ATTRIBUTE CHAP-Challenge 60 string
+ATTRIBUTE NAS-Port-Type 61 integer
+ATTRIBUTE Port-Limit 62 integer
+ATTRIBUTE Login-LAT-Port 63 integer
+ATTRIBUTE Connect-Info 77 string
+
+#
+# RFC3162 IPv6 attributes
+#
+ATTRIBUTE NAS-IPv6-Address 95 string
+ATTRIBUTE Framed-Interface-Id 96 string
+ATTRIBUTE Framed-IPv6-Prefix 97 string
+ATTRIBUTE Login-IPv6-Host 98 string
+ATTRIBUTE Framed-IPv6-Route 99 string
+ATTRIBUTE Framed-IPv6-Pool 100 string
+
+#
+# Experimental Non Protocol Attributes used by Cistron-Radiusd
+#
+ATTRIBUTE Huntgroup-Name 221 string
+ATTRIBUTE User-Category 1029 string
+ATTRIBUTE Group-Name 1030 string
+ATTRIBUTE Simultaneous-Use 1034 integer
+ATTRIBUTE Strip-User-Name 1035 integer
+ATTRIBUTE Fall-Through 1036 integer
+ATTRIBUTE Add-Port-To-IP-Address 1037 integer
+ATTRIBUTE Exec-Program 1038 string
+ATTRIBUTE Exec-Program-Wait 1039 string
+ATTRIBUTE Hint 1040 string
+
+#
+# Non-Protocol Attributes
+# These attributes are used internally by the server
+#
+ATTRIBUTE Expiration 21 date
+ATTRIBUTE Auth-Type 1000 integer
+ATTRIBUTE Menu 1001 string
+ATTRIBUTE Termination-Menu 1002 string
+ATTRIBUTE Prefix 1003 string
+ATTRIBUTE Suffix 1004 string
+ATTRIBUTE Group 1005 string
+ATTRIBUTE Crypt-Password 1006 string
+ATTRIBUTE Connect-Rate 1007 integer
+
+#
+# Integer Translations
+#
+
+# User Types
+
+VALUE Service-Type Login-User 1
+VALUE Service-Type Framed-User 2
+VALUE Service-Type Callback-Login-User 3
+VALUE Service-Type Callback-Framed-User 4
+VALUE Service-Type Outbound-User 5
+VALUE Service-Type Administrative-User 6
+VALUE Service-Type NAS-Prompt-User 7
+
+# Framed Protocols
+
+VALUE Framed-Protocol PPP 1
+VALUE Framed-Protocol SLIP 2
+
+# Framed Routing Values
+
+VALUE Framed-Routing None 0
+VALUE Framed-Routing Broadcast 1
+VALUE Framed-Routing Listen 2
+VALUE Framed-Routing Broadcast-Listen 3
+
+# Framed Compression Types
+
+VALUE Framed-Compression None 0
+VALUE Framed-Compression Van-Jacobson-TCP-IP 1
+
+# Login Services
+
+VALUE Login-Service Telnet 0
+VALUE Login-Service Rlogin 1
+VALUE Login-Service TCP-Clear 2
+VALUE Login-Service PortMaster 3
+
+# Status Types
+
+VALUE Acct-Status-Type Start 1
+VALUE Acct-Status-Type Stop 2
+VALUE Acct-Status-Type Alive 3
+VALUE Acct-Status-Type Accounting-On 7
+VALUE Acct-Status-Type Accounting-Off 8
+
+# Authentication Types
+
+VALUE Acct-Authentic RADIUS 1
+VALUE Acct-Authentic Local 2
+VALUE Acct-Authentic PowerLink128 100
+
+# Termination Options
+
+VALUE Termination-Action Default 0
+VALUE Termination-Action RADIUS-Request 1
+
+# NAS Port Types, available in 3.3.1 and later
+
+VALUE NAS-Port-Type Async 0
+VALUE NAS-Port-Type Sync 1
+VALUE NAS-Port-Type ISDN 2
+VALUE NAS-Port-Type ISDN-V120 3
+VALUE NAS-Port-Type ISDN-V110 4
+
+# Acct Terminate Causes, available in 3.3.2 and later
+
+VALUE Acct-Terminate-Cause User-Request 1
+VALUE Acct-Terminate-Cause Lost-Carrier 2
+VALUE Acct-Terminate-Cause Lost-Service 3
+VALUE Acct-Terminate-Cause Idle-Timeout 4
+VALUE Acct-Terminate-Cause Session-Timeout 5
+VALUE Acct-Terminate-Cause Admin-Reset 6
+VALUE Acct-Terminate-Cause Admin-Reboot 7
+VALUE Acct-Terminate-Cause Port-Error 8
+VALUE Acct-Terminate-Cause NAS-Error 9
+VALUE Acct-Terminate-Cause NAS-Request 10
+VALUE Acct-Terminate-Cause NAS-Reboot 11
+VALUE Acct-Terminate-Cause Port-Unneeded 12
+VALUE Acct-Terminate-Cause Port-Preempted 13
+VALUE Acct-Terminate-Cause Port-Suspended 14
+VALUE Acct-Terminate-Cause Service-Unavailable 15
+VALUE Acct-Terminate-Cause Callback 16
+VALUE Acct-Terminate-Cause User-Error 17
+VALUE Acct-Terminate-Cause Host-Request 18
+
+#
+# Non-Protocol Integer Translations
+#
+
+VALUE Auth-Type Local 0
+VALUE Auth-Type System 1
+VALUE Auth-Type SecurID 2
+VALUE Auth-Type Crypt-Local 3
+VALUE Auth-Type Reject 4
+
+#
+# Cistron extensions
+#
+VALUE Auth-Type Pam 253
+VALUE Auth-Type Accept 254
+
+#
+# Experimental Non-Protocol Integer Translations for Cistron-Radiusd
+#
+VALUE Fall-Through No 0
+VALUE Fall-Through Yes 1
+VALUE Add-Port-To-IP-Address No 0
+VALUE Add-Port-To-IP-Address Yes 1
+
+#
+# Configuration Values
+# uncomment these two lines to turn account expiration on
+#
+
+#VALUE Server-Config Password-Expiration 30
+#VALUE Server-Config Password-Warning 5
+
diff --git a/accel-pptpd/radius/radius.c b/accel-pptpd/radius/radius.c
new file mode 100644
index 00000000..10fef65f
--- /dev/null
+++ b/accel-pptpd/radius/radius.c
@@ -0,0 +1,74 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ppp.h"
+#include "pwdb.h"
+#include "radius.h"
+
+struct radius_pd_t
+{
+ struct ppp_pd_t pd;
+ struct ppp_t *ppp;
+};
+
+static struct ppp_notified_t notified;
+
+int cleartext_check(struct pwdb_t *pwdb, struct ppp_t *ppp, const char *username, const char *password)
+{
+ return PWDB_NO_IMPL;
+}
+int encrypted_check(struct pwdb_t *pwdb, struct ppp_t *ppp, const char *username, int type, va_list args)
+{
+ return PWDB_NO_IMPL;
+}
+
+
+static void ppp_started(struct ppp_notified_t *n, struct ppp_t *ppp)
+{
+ struct radius_pd_t *pd = malloc(sizeof(*pd));
+
+ memset(pd, 0, sizeof(*pd));
+ pd->pd.key = n;
+ pd->ppp = ppp;
+ list_add_tail(&pd->pd.entry, &ppp->pd_list);
+}
+
+static void ppp_finished(struct ppp_notified_t *n, struct ppp_t *ppp)
+{
+ struct ppp_pd_t *pd;
+ struct radius_pd_t *rpd;
+
+ list_for_each_entry(pd, &ppp->pd_list, entry) {
+ if (pd->key == &notified) {
+ rpd = container_of(pd, typeof(*rpd), pd);
+ list_del(&pd->entry);
+ free(rpd);
+ return;
+ }
+ }
+}
+
+struct pwdb_t pwdb = {
+ .cleartext_check = cleartext_check,
+ .encrypted_check = encrypted_check,
+};
+
+static struct ppp_notified_t notified = {
+ .started = ppp_started,
+ .finished = ppp_finished,
+};
+
+static void __init radius_init(void)
+{
+ char *dict = conf_get_opt("radius", "dictionary");
+ if (!dict) {
+ fprintf(stderr, "radius: dictionary not specified\n");
+ _exit(EXIT_FAILURE);
+ }
+ if (!rad_load_dict(dict))
+ _exit(EXIT_FAILURE);
+ ppp_register_notified(&notified);
+}
+
diff --git a/accel-pptpd/radius/radius.h b/accel-pptpd/radius/radius.h
new file mode 100644
index 00000000..aac1cd00
--- /dev/null
+++ b/accel-pptpd/radius/radius.h
@@ -0,0 +1,28 @@
+#ifndef __RADIUS_H
+#define __RADIUS_H
+
+#include <netinet/in.h>
+
+#define ATTR_TYPE_INTEGER 0
+#define ATTR_TYPE_STRING 1
+#define ATTR_TYPE_DATE 2
+#define ATTR_TYPE_IPADDR 3
+
+typedef union
+{
+ int integer;
+ const char *string;
+ time_t date;
+ in_addr_t ipaddr;
+} rad_value_t;
+
+struct rad_dict_t
+{
+ struct list_head items;
+};
+
+void *rad_load_dict(const char *fname);
+void rad_free_dict(struct rad_dict_t *dict);
+
+#endif
+