Annotation of embedaddon/strongswan/src/charon-cmd/cmd/cmd_creds.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2013 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * Copyright (C) 2013 Martin Willi
6: * Copyright (C) 2013 revosec AG
7: *
8: * This program is free software; you can redistribute it and/or modify it
9: * under the terms of the GNU General Public License as published by the
10: * Free Software Foundation; either version 2 of the License, or (at your
11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12: *
13: * This program is distributed in the hope that it will be useful, but
14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16: * for more details.
17: */
18:
19: #include "cmd_creds.h"
20:
21: #include <unistd.h>
22:
23: #include <utils/debug.h>
24: #include <credentials/sets/mem_cred.h>
25: #include <credentials/containers/pkcs12.h>
26: #include <credentials/sets/callback_cred.h>
27:
28: typedef struct private_cmd_creds_t private_cmd_creds_t;
29:
30: /**
31: * Private data of an cmd_creds_t object.
32: */
33: struct private_cmd_creds_t {
34:
35: /**
36: * Public cmd_creds_t interface.
37: */
38: cmd_creds_t public;
39:
40: /**
41: * Reused in-memory credential set
42: */
43: mem_cred_t *creds;
44:
45: /**
46: * Callback credential set to get secrets
47: */
48: callback_cred_t *cb;
49:
50: /**
51: * Kind of secret we recently prompted
52: */
53: shared_key_type_t prompted;
54:
55: /**
56: * Path to ssh-agent socket
57: */
58: char *agent;
59:
60: /**
61: * Local identity
62: */
63: char *identity;
64: };
65:
66: /**
67: * Callback function to prompt for secret
68: */
69: static shared_key_t* callback_shared(private_cmd_creds_t *this,
70: shared_key_type_t type,
71: identification_t *me, identification_t *other,
72: id_match_t *match_me, id_match_t *match_other)
73: {
74: shared_key_t *shared;
75: char *label, *pwd = NULL;
76:
77: if (type == this->prompted)
78: {
79: return NULL;
80: }
81: switch (type)
82: {
83: case SHARED_EAP:
84: label = "EAP password: ";
85: break;
86: case SHARED_IKE:
87: label = "Preshared Key: ";
88: break;
89: case SHARED_PRIVATE_KEY_PASS:
90: label = "Password: ";
91: break;
92: case SHARED_PIN:
93: label = "PIN: ";
94: break;
95: default:
96: return NULL;
97: }
98: #ifdef HAVE_GETPASS
99: pwd = getpass(label);
100: #endif
101: if (!pwd || strlen(pwd) == 0)
102: {
103: return NULL;
104: }
105: this->prompted = type;
106: if (match_me)
107: {
108: *match_me = ID_MATCH_PERFECT;
109: }
110: if (match_other)
111: {
112: *match_other = ID_MATCH_PERFECT;
113: }
114: shared = shared_key_create(type, chunk_clone(chunk_from_str(pwd)));
115: /* cache password in case it is required more than once */
116: this->creds->add_shared(this->creds, shared, NULL);
117: return shared->get_ref(shared);
118: }
119:
120: /**
121: * Load a trusted certificate from path
122: */
123: static void load_cert(private_cmd_creds_t *this, char *path)
124: {
125: certificate_t *cert;
126:
127: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
128: BUILD_FROM_FILE, path, BUILD_END);
129: if (!cert)
130: {
131: DBG1(DBG_CFG, "loading certificate from '%s' failed", path);
132: exit(1);
133: }
134: this->creds->add_cert(this->creds, TRUE, cert);
135: }
136:
137: /**
138: * Load a private key of given kind from path
139: */
140: static void load_key(private_cmd_creds_t *this, key_type_t type, char *path)
141: {
142: private_key_t *privkey;
143:
144: privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
145: BUILD_FROM_FILE, path, BUILD_END);
146: if (!privkey)
147: {
148: DBG1(DBG_CFG, "loading %N private key from '%s' failed",
149: key_type_names, type, path);
150: exit(1);
151: }
152: this->creds->add_key(this->creds, privkey);
153: }
154:
155: /**
156: * Load a private and public key via ssh-agent
157: */
158: static void load_agent(private_cmd_creds_t *this)
159: {
160: private_key_t *privkey;
161: public_key_t *pubkey;
162: identification_t *id;
163: certificate_t *cert;
164:
165: privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
166: BUILD_AGENT_SOCKET, this->agent, BUILD_END);
167: if (!privkey)
168: {
169: DBG1(DBG_CFG, "failed to load private key from ssh-agent");
170: exit(1);
171: }
172: pubkey = privkey->get_public_key(privkey);
173: if (!pubkey)
174: {
175: DBG1(DBG_CFG, "failed to load public key from ssh-agent");
176: privkey->destroy(privkey);
177: exit(1);
178: }
179: id = identification_create_from_string(this->identity);
180: cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
181: CERT_TRUSTED_PUBKEY, BUILD_PUBLIC_KEY, pubkey,
182: BUILD_SUBJECT, id, BUILD_END);
183: pubkey->destroy(pubkey);
184: id->destroy(id);
185: if (!cert)
186: {
187: DBG1(DBG_CFG, "failed to create certificate for ssh-agent public key");
188: privkey->destroy(privkey);
189: exit(1);
190: }
191: this->creds->add_cert(this->creds, TRUE, cert);
192: this->creds->add_key(this->creds, privkey);
193: }
194:
195: /**
196: * Load a PKCS#12 file from path
197: */
198: static void load_pkcs12(private_cmd_creds_t *this, char *path)
199: {
200: enumerator_t *enumerator;
201: certificate_t *cert;
202: private_key_t *key;
203: container_t *container;
204: pkcs12_t *pkcs12;
205:
206: container = lib->creds->create(lib->creds, CRED_CONTAINER, CONTAINER_PKCS12,
207: BUILD_FROM_FILE, path, BUILD_END);
208: if (!container)
209: {
210: DBG1(DBG_CFG, "loading PKCS#12 file '%s' failed", path);
211: exit(1);
212: }
213: pkcs12 = (pkcs12_t*)container;
214: enumerator = pkcs12->create_cert_enumerator(pkcs12);
215: while (enumerator->enumerate(enumerator, &cert))
216: {
217: this->creds->add_cert(this->creds, TRUE, cert->get_ref(cert));
218: }
219: enumerator->destroy(enumerator);
220: enumerator = pkcs12->create_key_enumerator(pkcs12);
221: while (enumerator->enumerate(enumerator, &key))
222: {
223: this->creds->add_key(this->creds, key->get_ref(key));
224: }
225: enumerator->destroy(enumerator);
226: container->destroy(container);
227: }
228:
229: METHOD(cmd_creds_t, handle, bool,
230: private_cmd_creds_t *this, cmd_option_type_t opt, char *arg)
231: {
232: switch (opt)
233: {
234: case CMD_OPT_CERT:
235: load_cert(this, arg);
236: break;
237: case CMD_OPT_RSA:
238: load_key(this, KEY_RSA, arg);
239: break;
240: case CMD_OPT_PKCS12:
241: load_pkcs12(this, arg);
242: break;
243: case CMD_OPT_IDENTITY:
244: this->identity = arg;
245: break;
246: case CMD_OPT_AGENT:
247: this->agent = arg ?: getenv("SSH_AUTH_SOCK");
248: if (!this->agent)
249: {
250: DBG1(DBG_CFG, "no ssh-agent socket defined");
251: exit(1);
252: }
253: break;
254: default:
255: return FALSE;
256: }
257: if (this->agent && this->identity)
258: {
259: load_agent(this);
260: /* only do this once */
261: this->agent = NULL;
262: }
263: return TRUE;
264: }
265:
266: METHOD(cmd_creds_t, destroy, void,
267: private_cmd_creds_t *this)
268: {
269: lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
270: lib->credmgr->remove_set(lib->credmgr, &this->cb->set);
271: this->creds->destroy(this->creds);
272: this->cb->destroy(this->cb);
273: free(this);
274: }
275:
276: /**
277: * See header
278: */
279: cmd_creds_t *cmd_creds_create()
280: {
281: private_cmd_creds_t *this;
282:
283: INIT(this,
284: .public = {
285: .handle = _handle,
286: .destroy = _destroy,
287: },
288: .creds = mem_cred_create(),
289: .prompted = SHARED_ANY,
290: );
291: this->cb = callback_cred_create_shared((void*)callback_shared, this);
292:
293: lib->credmgr->add_set(lib->credmgr, &this->creds->set);
294: lib->credmgr->add_set(lib->credmgr, &this->cb->set);
295:
296: return &this->public;
297: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>