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