Annotation of embedaddon/strongswan/src/libcharon/plugins/xauth_pam/xauth_pam.c, revision 1.1.1.1
1.1 misho 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 "xauth_pam.h"
17:
18: #include <daemon.h>
19: #include <library.h>
20:
21: #include <security/pam_appl.h>
22:
23: typedef struct private_xauth_pam_t private_xauth_pam_t;
24:
25: /**
26: * Private data of an xauth_pam_t object.
27: */
28: struct private_xauth_pam_t {
29:
30: /**
31: * Public interface.
32: */
33: xauth_pam_t public;
34:
35: /**
36: * ID of the peer
37: */
38: identification_t *peer;
39: };
40:
41: METHOD(xauth_method_t, initiate, status_t,
42: private_xauth_pam_t *this, cp_payload_t **out)
43: {
44: cp_payload_t *cp;
45:
46: cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
47: cp->add_attribute(cp, configuration_attribute_create_chunk(
48: PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
49: cp->add_attribute(cp, configuration_attribute_create_chunk(
50: PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));
51: *out = cp;
52: return NEED_MORE;
53: }
54:
55: /**
56: * PAM conv callback function
57: */
58: static int auth_conv(int num_msg, const struct pam_message **msg,
59: struct pam_response **resp, char *password)
60: {
61: struct pam_response *response;
62:
63: if (num_msg != 1)
64: {
65: return PAM_CONV_ERR;
66: }
67: response = malloc(sizeof(struct pam_response));
68: response->resp = strdup(password);
69: response->resp_retcode = 0;
70: *resp = response;
71: return PAM_SUCCESS;
72: }
73:
74: /**
75: * Authenticate a username/password using PAM
76: */
77: static bool authenticate(char *service, char *user, char *password)
78: {
79: pam_handle_t *pamh = NULL;
80: static struct pam_conv conv;
81: int ret;
82:
83: conv.conv = (void*)auth_conv;
84: conv.appdata_ptr = password;
85:
86: ret = pam_start(service, user, &conv, &pamh);
87: if (ret != PAM_SUCCESS)
88: {
89: DBG1(DBG_IKE, "XAuth pam_start for '%s' failed: %s",
90: user, pam_strerror(pamh, ret));
91: return FALSE;
92: }
93: ret = pam_authenticate(pamh, 0);
94: if (ret == PAM_SUCCESS)
95: {
96: ret = pam_acct_mgmt(pamh, 0);
97: if (ret != PAM_SUCCESS)
98: {
99: DBG1(DBG_IKE, "XAuth pam_acct_mgmt for '%s' failed: %s",
100: user, pam_strerror(pamh, ret));
101: }
102: }
103: else
104: {
105: DBG1(DBG_IKE, "XAuth pam_authenticate for '%s' failed: %s",
106: user, pam_strerror(pamh, ret));
107: }
108: pam_end(pamh, ret);
109: return ret == PAM_SUCCESS;
110: }
111:
112: /**
113: * Convert configuration attribute content to a null-terminated string
114: */
115: static void attr2string(char *buf, size_t len, chunk_t chunk)
116: {
117: if (chunk.len && chunk.len < len)
118: {
119: chunk_t sane;
120:
121: chunk_printable(chunk, &sane, '?');
122: snprintf(buf, len, "%.*s", (int)sane.len, sane.ptr);
123: chunk_clear(&sane);
124: }
125: }
126:
127: METHOD(xauth_method_t, process, status_t,
128: private_xauth_pam_t *this, cp_payload_t *in, cp_payload_t **out)
129: {
130: char *service, user[128] = "", pass[128] = "", *pos;
131: configuration_attribute_t *attr;
132: enumerator_t *enumerator;
133: chunk_t chunk;
134:
135: enumerator = in->create_attribute_enumerator(in);
136: while (enumerator->enumerate(enumerator, &attr))
137: {
138: switch (attr->get_type(attr))
139: {
140: case XAUTH_USER_NAME:
141: chunk = attr->get_chunk(attr);
142: /* trim to username part if email address given */
143: if (lib->settings->get_bool(lib->settings,
144: "%s.plugins.xauth-pam.trim_email",
145: TRUE, lib->ns))
146: {
147: pos = memchr(chunk.ptr, '@', chunk.len);
148: if (pos)
149: {
150: chunk.len = (u_char*)pos - chunk.ptr;
151: }
152: }
153: attr2string(user, sizeof(user), chunk);
154: break;
155: case XAUTH_USER_PASSWORD:
156: chunk = attr->get_chunk(attr);
157: if (chunk.len && chunk.ptr[chunk.len - 1] == 0)
158: { /* fix null-terminated passwords (Android etc.) */
159: chunk.len -= 1;
160: }
161: attr2string(pass, sizeof(pass), chunk);
162: break;
163: default:
164: break;
165: }
166: }
167: enumerator->destroy(enumerator);
168:
169: if (!user[0] || !pass[0])
170: {
171: DBG1(DBG_IKE, "peer did not respond to our XAuth request");
172: return FAILED;
173: }
174:
175: this->peer->destroy(this->peer);
176: this->peer = identification_create_from_string(user);
177:
178: /* Look for PAM service, with a legacy fallback for the eap-gtc plugin.
179: * Default to "login". */
180: service = lib->settings->get_str(lib->settings,
181: "%s.plugins.xauth-pam.pam_service",
182: lib->settings->get_str(lib->settings,
183: "%s.plugins.eap-gtc.pam_service", "login", lib->ns),
184: lib->ns);
185:
186: if (authenticate(service, user, pass))
187: {
188: DBG1(DBG_IKE, "PAM authentication of '%s' successful", user);
189: return SUCCESS;
190: }
191: return FAILED;
192: }
193:
194: METHOD(xauth_method_t, get_identity, identification_t*,
195: private_xauth_pam_t *this)
196: {
197: return this->peer;
198: }
199:
200: METHOD(xauth_method_t, destroy, void,
201: private_xauth_pam_t *this)
202: {
203: this->peer->destroy(this->peer);
204: free(this);
205: }
206:
207: /*
208: * Described in header.
209: */
210: xauth_pam_t *xauth_pam_create_server(identification_t *server,
211: identification_t *peer, char *profile)
212: {
213: private_xauth_pam_t *this;
214:
215: INIT(this,
216: .public = {
217: .xauth_method = {
218: .initiate = _initiate,
219: .process = _process,
220: .get_identity = _get_identity,
221: .destroy = _destroy,
222: },
223: },
224: .peer = peer->clone(peer),
225: );
226:
227: return &this->public;
228: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>