pki: Add --dn command to extract the subject DN of a certificate
[strongswan.git] / src / pki / commands / dn.c
1 /*
2 * Copyright (C) 2015 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
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 "pki.h"
17
18 #include <credentials/certificates/certificate.h>
19
20 #include <errno.h>
21
22 /**
23 * Extract subject DN
24 */
25 static int dn()
26 {
27 identification_t *id;
28 certificate_t *cert;
29 chunk_t chunk;
30 enum {
31 FORMAT_CONFIG,
32 FORMAT_HEX,
33 FORMAT_BASE64,
34 FORMAT_BINARY,
35 } format = FORMAT_CONFIG;
36 char *arg, *file = NULL, *fmt;
37
38 while (TRUE)
39 {
40 switch (command_getopt(&arg))
41 {
42 case 'h':
43 return command_usage(NULL);
44 case 'f':
45 if (streq(arg, "hex"))
46 {
47 format = FORMAT_HEX;
48 }
49 else if (streq(arg, "base64"))
50 {
51 format = FORMAT_BASE64;
52 }
53 else if (streq(arg, "bin"))
54 {
55 format = FORMAT_BINARY;
56 }
57 else if (!streq(arg, "config"))
58 {
59 return command_usage( "invalid output format");
60 }
61 continue;
62 case 'i':
63 file = arg;
64 continue;
65 case EOF:
66 break;
67 default:
68 return command_usage("invalid --print option");
69 }
70 break;
71 }
72 if (file)
73 {
74 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
75 BUILD_FROM_FILE, file, BUILD_END);
76 }
77 else
78 {
79 chunk_t chunk;
80
81 set_file_mode(stdin, CERT_ASN1_DER);
82 if (!chunk_from_fd(0, &chunk))
83 {
84 fprintf(stderr, "reading input failed: %s\n", strerror(errno));
85 return 1;
86 }
87 cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
88 BUILD_BLOB, chunk, BUILD_END);
89 free(chunk.ptr);
90 }
91 if (!cert)
92 {
93 fprintf(stderr, "parsing input failed\n");
94 return 1;
95 }
96 id = cert->get_subject(cert);
97 if (!id)
98 {
99 fprintf(stderr, "failed to get certificate's subject DN\n");
100 cert->destroy(cert);
101 return 1;
102 }
103 fmt = "%.*s\n";
104 switch (format)
105 {
106 case FORMAT_CONFIG:
107 fmt = "\"asn1dn:#%.*s\"\n";
108 /* fall-through */
109 case FORMAT_HEX:
110 chunk = chunk_to_hex(id->get_encoding(id), NULL, FALSE);
111 printf(fmt, (int)chunk.len, chunk.ptr);
112 chunk_free(&chunk);
113 break;
114 case FORMAT_BASE64:
115 chunk = chunk_to_base64(id->get_encoding(id), NULL);
116 printf(fmt, (int)chunk.len, chunk.ptr);
117 chunk_free(&chunk);
118 break;
119 case FORMAT_BINARY:
120 chunk = id->get_encoding(id);
121 if (fwrite(chunk.ptr, chunk.len, 1, stdout) != 1)
122 {
123 fprintf(stderr, "writing subject DN failed\n");
124 }
125 break;
126 }
127 cert->destroy(cert);
128 return 0;
129 }
130
131 /**
132 * Register the command.
133 */
134 static void __attribute__ ((constructor))reg()
135 {
136 command_register((command_t)
137 { dn, 'd', "dn",
138 "extract the subject DN of an X.509 certificate",
139 {"[--in file] [--format config|hex|base64|bin]"},
140 {
141 {"help", 'h', 0, "show usage information"},
142 {"in", 'i', 1, "input file, default: stdin"},
143 {"format", 'f', 1, "output format, default: config"},
144 }
145 });
146 }