]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libcharon/plugins/radattr/radattr_listener.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libcharon / plugins / radattr / radattr_listener.c
CommitLineData
caf4b88e
MW
1/*
2 * Copyright (C) 2012 Martin Willi
19ef2aec
TB
3 *
4 * Copyright (C) secunet Security Networks AG
caf4b88e
MW
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17#include "radattr_listener.h"
18
3ccc8a19
MW
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <unistd.h>
22#include <fcntl.h>
3ccc8a19
MW
23#include <errno.h>
24
caf4b88e
MW
25#include <daemon.h>
26
27#include <radius_message.h>
28
3ccc8a19
MW
29/**
30 * Maximum size of an attribute to add
31 */
32#define MAX_ATTR_SIZE 1024
33
caf4b88e
MW
34typedef struct private_radattr_listener_t private_radattr_listener_t;
35
36/**
37 * Private data of an radattr_listener_t object.
38 */
39struct private_radattr_listener_t {
40
41 /**
42 * Public radattr_listener_t interface.
43 */
44 radattr_listener_t public;
3ccc8a19
MW
45
46 /**
47 * Directory to look for attribute files
48 */
49 char *dir;
50
51 /**
52 * IKE_AUTH message ID to attribute
53 */
54 int mid;
caf4b88e
MW
55};
56
57/**
58 * Print RADIUS attributes found in IKE message notifies
59 */
60static void print_radius_attributes(private_radattr_listener_t *this,
61 message_t *message)
62{
63 radius_attribute_type_t type;
64 enumerator_t *enumerator;
65 notify_payload_t *notify;
66 payload_t *payload;
67 chunk_t data;
68
69 enumerator = message->create_payload_enumerator(message);
70 while (enumerator->enumerate(enumerator, &payload))
71 {
3ecfc83c 72 if (payload->get_type(payload) == PLV2_NOTIFY)
caf4b88e
MW
73 {
74 notify = (notify_payload_t*)payload;
75 if (notify->get_notify_type(notify) == RADIUS_ATTRIBUTE)
76 {
77 data = notify->get_notification_data(notify);
78 if (data.len >= 2)
79 {
80 type = data.ptr[0];
81 data = chunk_skip(data, 2);
82 if (chunk_printable(data, NULL, 0))
83 {
84 DBG1(DBG_IKE, "received RADIUS %N: %.*s",
85 radius_attribute_type_names, type,
86 (int)data.len, data.ptr);
87 }
88 else
89 {
90 DBG1(DBG_IKE, "received RADIUS %N: %#B",
91 radius_attribute_type_names, type, &data);
92
93 }
94 }
95 }
96 }
97 }
98 enumerator->destroy(enumerator);
99}
100
3ccc8a19
MW
101/**
102 * Add a RADIUS attribute from a client-ID specific file to an IKE message
103 */
104static void add_radius_attribute(private_radattr_listener_t *this,
2e3615e4 105 ike_sa_t *ike_sa, message_t *message)
3ccc8a19 106{
bb0b2031
MW
107 if (this->dir &&
108 (this->mid == -1 || message->get_message_id(message) == this->mid))
3ccc8a19 109 {
2e3615e4
MW
110 identification_t *id;
111 auth_cfg_t *auth;
3ccc8a19 112 char path[PATH_MAX];
b8d0103e 113 chunk_t *data;
3ccc8a19 114
2e3615e4
MW
115 auth = ike_sa->get_auth_cfg(ike_sa, TRUE);
116 id = auth->get(auth, AUTH_RULE_EAP_IDENTITY);
117 if (!id)
118 {
119 id = ike_sa->get_my_id(ike_sa);
120 }
121
3ccc8a19 122 snprintf(path, sizeof(path), "%s/%Y", this->dir, id);
b8d0103e
MW
123 data = chunk_map(path, FALSE);
124 if (data)
3ccc8a19 125 {
b8d0103e 126 if (data->len >= 2)
3ccc8a19 127 {
b8d0103e
MW
128 DBG1(DBG_CFG, "adding RADIUS %N attribute",
129 radius_attribute_type_names, data->ptr[0]);
130 message->add_notify(message, FALSE, RADIUS_ATTRIBUTE, *data);
3ccc8a19 131 }
b8d0103e 132 chunk_unmap(data);
3ccc8a19
MW
133 }
134 else
135 {
136 DBG1(DBG_CFG, "reading RADIUS attribute '%s' failed: %s",
137 path, strerror(errno));
138 }
139 }
140}
141
caf4b88e
MW
142METHOD(listener_t, message, bool,
143 private_radattr_listener_t *this,
b1f2f05c 144 ike_sa_t *ike_sa, message_t *message, bool incoming, bool plain)
caf4b88e 145{
b1f2f05c 146 if (plain && ike_sa->supports_extension(ike_sa, EXT_STRONGSWAN) &&
4bbd9430 147 message->get_exchange_type(message) == IKE_AUTH &&
3ecfc83c 148 message->get_payload(message, PLV2_EAP))
caf4b88e
MW
149 {
150 if (incoming)
151 {
152 print_radius_attributes(this, message);
153 }
3ccc8a19
MW
154 else
155 {
2e3615e4 156 add_radius_attribute(this, ike_sa, message);
3ccc8a19 157 }
caf4b88e
MW
158 }
159 return TRUE;
160}
161
162
163METHOD(radattr_listener_t, destroy, void,
164 private_radattr_listener_t *this)
165{
166 free(this);
167}
168
169/**
170 * See header
171 */
172radattr_listener_t *radattr_listener_create()
173{
174 private_radattr_listener_t *this;
175
176 INIT(this,
177 .public = {
178 .listener = {
179 .message = _message,
180 },
181 .destroy = _destroy,
182 },
3ccc8a19 183 .dir = lib->settings->get_str(lib->settings,
d223fe80 184 "%s.plugins.radattr.dir", NULL, lib->ns),
3ccc8a19 185 .mid = lib->settings->get_int(lib->settings,
d223fe80 186 "%s.plugins.radattr.message_id", -1, lib->ns),
caf4b88e
MW
187 );
188
189 return &this->public;
190}