]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libpttls/sasl/sasl_plain/sasl_plain.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libpttls / sasl / sasl_plain / sasl_plain.c
CommitLineData
2ae0c9e6
MW
1/*
2 * Copyright (C) 2013 Martin Willi
19ef2aec
TB
3 *
4 * Copyright (C) secunet Security Networks AG
2ae0c9e6
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 "sasl_plain.h"
18
19#include <utils/debug.h>
20
21typedef struct private_sasl_plain_t private_sasl_plain_t;
22
23/**
24 * Private data of an sasl_plain_t object.
25 */
26struct private_sasl_plain_t {
27
28 /**
29 * Public sasl_plain_t interface.
30 */
31 sasl_plain_t public;
32
33 /**
34 * Client identity
35 */
36 identification_t *client;
37};
38
97b1d39d
AS
39METHOD(sasl_mechanism_t, get_client, identification_t*,
40 private_sasl_plain_t *this)
41{
42 return this->client;
43}
44
2ae0c9e6
MW
45METHOD(sasl_mechanism_t, get_name, char*,
46 private_sasl_plain_t *this)
47{
48 return "PLAIN";
49}
50
51METHOD(sasl_mechanism_t, build_server, status_t,
52 private_sasl_plain_t *this, chunk_t *message)
53{
54 /* gets never called */
55 return FAILED;
56}
57
58METHOD(sasl_mechanism_t, process_server, status_t,
59 private_sasl_plain_t *this, chunk_t message)
60{
61 chunk_t authz, authi, password;
2ae0c9e6
MW
62 shared_key_t *shared;
63 u_char *pos;
64
65 pos = memchr(message.ptr, 0, message.len);
66 if (!pos)
67 {
68 DBG1(DBG_CFG, "invalid authz encoding");
69 return FAILED;
70 }
71 authz = chunk_create(message.ptr, pos - message.ptr);
72 message = chunk_skip(message, authz.len + 1);
73 pos = memchr(message.ptr, 0, message.len);
74 if (!pos)
75 {
76 DBG1(DBG_CFG, "invalid authi encoding");
77 return FAILED;
78 }
79 authi = chunk_create(message.ptr, pos - message.ptr);
80 password = chunk_skip(message, authi.len + 1);
97b1d39d
AS
81 DESTROY_IF(this->client);
82 this->client = identification_create_from_data(authi);
83 shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, this->client,
84 NULL);
2ae0c9e6
MW
85 if (!shared)
86 {
97b1d39d 87 DBG1(DBG_CFG, "no shared secret found for '%Y'", this->client);
2ae0c9e6
MW
88 return FAILED;
89 }
161a0157 90 if (!chunk_equals_const(shared->get_key(shared), password))
2ae0c9e6 91 {
97b1d39d 92 DBG1(DBG_CFG, "shared secret for '%Y' does not match", this->client);
2ae0c9e6
MW
93 shared->destroy(shared);
94 return FAILED;
95 }
2ae0c9e6
MW
96 shared->destroy(shared);
97 return SUCCESS;
98}
99
100METHOD(sasl_mechanism_t, build_client, status_t,
101 private_sasl_plain_t *this, chunk_t *message)
102{
103 shared_key_t *shared;
104 chunk_t password;
105 char buf[256];
106 ssize_t len;
107
108 /* we currently use the EAP type of shared secret */
109 shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP,
110 this->client, NULL);
111 if (!shared)
112 {
113 DBG1(DBG_CFG, "no shared secret found for %Y", this->client);
114 return FAILED;
115 }
116
117 password = shared->get_key(shared);
118 len = snprintf(buf, sizeof(buf), "%s%c%Y%c%.*s",
119 "", 0, this->client, 0,
120 (int)password.len, password.ptr);
9cc606d2
AS
121 shared->destroy(shared);
122
2ae0c9e6
MW
123 if (len < 0 || len >= sizeof(buf))
124 {
125 return FAILED;
126 }
127 *message = chunk_clone(chunk_create(buf, len));
9cc606d2 128
2ae0c9e6
MW
129 return NEED_MORE;
130}
131
132METHOD(sasl_mechanism_t, process_client, status_t,
133 private_sasl_plain_t *this, chunk_t message)
134{
135 /* if the server sends a result, authentication successful */
136 return SUCCESS;
137}
138
139METHOD(sasl_mechanism_t, destroy, void,
140 private_sasl_plain_t *this)
141{
142 DESTROY_IF(this->client);
143 free(this);
144}
145
146/**
147 * See header
148 */
149sasl_plain_t *sasl_plain_create(char *name, identification_t *client)
150{
151 private_sasl_plain_t *this;
152
153 if (!streq(get_name(NULL), name))
154 {
155 return NULL;
156 }
157
158 INIT(this,
159 .public = {
160 .sasl = {
161 .get_name = _get_name,
97b1d39d 162 .get_client = _get_client,
2ae0c9e6
MW
163 .destroy = _destroy,
164 },
165 },
166 );
167
168 if (client)
169 {
170 this->public.sasl.build = _build_client;
171 this->public.sasl.process = _process_client;
172 this->client = client->clone(client);
173 }
174 else
175 {
176 this->public.sasl.build = _build_server;
177 this->public.sasl.process = _process_server;
178 }
179 return &this->public;
180}