2 * Copyright (C) 2012-2014 Tobias Brunner
3 * Copyright (C) 2009 Martin Willi
4 * Hochschule fuer Technik Rapperswil
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>.
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
25 #include <utils/debug.h>
26 #include <credentials/sets/mem_cred.h>
27 #include <credentials/sets/callback_cred.h>
30 * Convert a form string to a encoding type
32 bool get_form(char *form
, cred_encoding_type_t
*enc
, credential_type_t type
)
34 if (streq(form
, "der"))
38 case CRED_CERTIFICATE
:
41 case CRED_PRIVATE_KEY
:
42 *enc
= PRIVKEY_ASN1_DER
;
45 /* der encoded keys usually contain the complete
46 * SubjectPublicKeyInfo */
47 *enc
= PUBKEY_SPKI_ASN1_DER
;
53 else if (streq(form
, "pem"))
57 case CRED_CERTIFICATE
:
60 case CRED_PRIVATE_KEY
:
70 else if (streq(form
, "pgp"))
74 case CRED_PRIVATE_KEY
:
84 else if (streq(form
, "dnskey"))
95 else if (streq(form
, "sshkey"))
100 *enc
= PUBKEY_SSHKEY
;
110 * Convert a time string to struct tm using strptime format
112 static bool convert_time(char *str
, char *format
, struct tm
*tm
)
120 format
= "%d.%m.%y %T";
123 end
= strptime(str
, format
, tm
);
124 if (end
== NULL
|| *end
!= '\0')
130 #else /* !HAVE_STRPTIME */
134 fprintf(stderr
, "custom datetime string format not supported\n");
138 if (sscanf(str
, "%d.%d.%d %d:%d:%d",
139 &tm
->tm_mday
, &tm
->tm_mon
, &tm
->tm_year
,
140 &tm
->tm_hour
, &tm
->tm_min
, &tm
->tm_sec
) != 6)
144 /* strptime() interprets two-digit years > 68 as 19xx, do the same here.
145 * mktime() expects years based on 1900 */
146 if (tm
->tm_year
<= 68)
150 else if (tm
->tm_year
>= 1900)
151 { /* looks like four digits? */
154 /* month is specified from 0-11 */
156 /* automatically detect daylight saving time */
160 #endif /* !HAVE_STRPTIME */
166 bool calculate_lifetime(char *format
, char *nbstr
, char *nastr
, time_t span
,
167 time_t *nb
, time_t *na
)
174 localtime_r(&now
, &tm
);
177 if (!convert_time(nbstr
, format
, &tm
))
188 localtime_r(&now
, &tm
);
191 if (!convert_time(nastr
, format
, &tm
))
214 * Set output file mode appropriate for credential encoding form on Windows
216 void set_file_mode(FILE *stream
, cred_encoding_type_t enc
)
226 /* keep default text mode */
229 /* switch to binary mode */
235 _setmode(fd
, _O_BINARY
);
241 * Described in header
243 hash_algorithm_t
get_default_digest(private_key_t
*private)
245 enumerator_t
*enumerator
;
246 signature_scheme_t scheme
;
247 hash_algorithm_t alg
= HASH_UNKNOWN
;
249 enumerator
= signature_schemes_for_key(private->get_type(private),
250 private->get_keysize(private));
251 if (enumerator
->enumerate(enumerator
, &scheme
))
253 alg
= hasher_from_signature_scheme(scheme
);
255 enumerator
->destroy(enumerator
);
257 /* default to SHA-256 */
258 return alg
== HASH_UNKNOWN
? HASH_SHA256
: alg
;
262 * Callback credential set pki uses
264 static callback_cred_t
*cb_set
;
267 * Credential set to cache entered secrets
269 static mem_cred_t
*cb_creds
;
271 static shared_key_type_t prompted
;
274 * Callback function to receive credentials
276 static shared_key_t
* cb(void *data
, shared_key_type_t type
,
277 identification_t
*me
, identification_t
*other
,
278 id_match_t
*match_me
, id_match_t
*match_other
)
280 char buf
[64], *label
, *secret
= NULL
;
281 shared_key_t
*shared
;
283 if (prompted
== type
)
290 label
= "Smartcard PIN";
292 case SHARED_PRIVATE_KEY_PASS
:
293 label
= "Private key passphrase";
298 snprintf(buf
, sizeof(buf
), "%s: ", label
);
300 secret
= getpass(buf
);
302 if (secret
&& strlen(secret
))
307 *match_me
= ID_MATCH_PERFECT
;
311 *match_other
= ID_MATCH_NONE
;
313 shared
= shared_key_create(type
, chunk_clone(chunk_from_str(secret
)));
314 /* cache password in case it is required more than once */
315 cb_creds
->add_shared(cb_creds
, shared
, NULL
);
316 return shared
->get_ref(shared
);
322 * Register PIN/Passphrase callback function
324 static void add_callback()
326 cb_set
= callback_cred_create_shared(cb
, NULL
);
327 lib
->credmgr
->add_set(lib
->credmgr
, &cb_set
->set
);
328 cb_creds
= mem_cred_create();
329 lib
->credmgr
->add_set(lib
->credmgr
, &cb_creds
->set
);
333 * Unregister PIN/Passphrase callback function
335 static void remove_callback()
337 lib
->credmgr
->remove_set(lib
->credmgr
, &cb_creds
->set
);
338 cb_creds
->destroy(cb_creds
);
339 lib
->credmgr
->remove_set(lib
->credmgr
, &cb_set
->set
);
340 cb_set
->destroy(cb_set
);
344 * Library initialization and operation parsing
346 int main(int argc
, char *argv
[])
348 atexit(library_deinit
);
349 if (!library_init(NULL
, "pki"))
351 exit(SS_RC_LIBSTRONGSWAN_INTEGRITY
);
353 if (lib
->integrity
&&
354 !lib
->integrity
->check_file(lib
->integrity
, "pki", argv
[0]))
356 fprintf(stderr
, "integrity check of pki failed\n");
357 exit(SS_RC_DAEMON_INTEGRITY
);
359 if (!lib
->plugins
->load(lib
->plugins
,
360 lib
->settings
->get_str(lib
->settings
, "pki.load", PLUGINS
)))
362 exit(SS_RC_INITIALIZATION_FAILED
);
366 atexit(remove_callback
);
367 return command_dispatch(argc
, argv
);