~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source4/heimdal/lib/hx509/req.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2006 Kungliga Tekniska Högskolan
 
3
 * (Royal Institute of Technology, Stockholm, Sweden).
 
4
 * All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 *
 
10
 * 1. Redistributions of source code must retain the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer.
 
12
 *
 
13
 * 2. Redistributions in binary form must reproduce the above copyright
 
14
 *    notice, this list of conditions and the following disclaimer in the
 
15
 *    documentation and/or other materials provided with the distribution.
 
16
 *
 
17
 * 3. Neither the name of the Institute nor the names of its contributors
 
18
 *    may be used to endorse or promote products derived from this software
 
19
 *    without specific prior written permission.
 
20
 *
 
21
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 
22
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
23
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
24
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 
25
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
26
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
27
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
28
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
29
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
30
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
31
 * SUCH DAMAGE.
 
32
 */
 
33
 
 
34
#include "hx_locl.h"
 
35
#include <pkcs10_asn1.h>
 
36
RCSID("$Id$");
 
37
 
 
38
struct hx509_request_data {
 
39
    hx509_name name;
 
40
    SubjectPublicKeyInfo key;
 
41
    ExtKeyUsage eku;
 
42
    GeneralNames san;
 
43
};
 
44
 
 
45
/*
 
46
 *
 
47
 */
 
48
 
 
49
int
 
50
_hx509_request_init(hx509_context context, hx509_request *req)
 
51
{
 
52
    *req = calloc(1, sizeof(**req));
 
53
    if (*req == NULL)
 
54
        return ENOMEM;
 
55
 
 
56
    return 0;
 
57
}
 
58
 
 
59
void
 
60
_hx509_request_free(hx509_request *req)
 
61
{
 
62
    if ((*req)->name)
 
63
        hx509_name_free(&(*req)->name);
 
64
    free_SubjectPublicKeyInfo(&(*req)->key);
 
65
    free_ExtKeyUsage(&(*req)->eku);
 
66
    free_GeneralNames(&(*req)->san);
 
67
    memset(*req, 0, sizeof(**req));
 
68
    free(*req);
 
69
    *req = NULL;
 
70
}
 
71
 
 
72
int
 
73
_hx509_request_set_name(hx509_context context,
 
74
                        hx509_request req,
 
75
                        hx509_name name)
 
76
{
 
77
    if (req->name)
 
78
        hx509_name_free(&req->name);
 
79
    if (name) {
 
80
        int ret = hx509_name_copy(context, name, &req->name);
 
81
        if (ret)
 
82
            return ret;
 
83
    }
 
84
    return 0;
 
85
}
 
86
 
 
87
int
 
88
_hx509_request_get_name(hx509_context context,
 
89
                        hx509_request req,
 
90
                        hx509_name *name)
 
91
{
 
92
    if (req->name == NULL) {
 
93
        hx509_set_error_string(context, 0, EINVAL, "Request have no name");
 
94
        return EINVAL;
 
95
    }
 
96
    return hx509_name_copy(context, req->name, name);
 
97
}
 
98
 
 
99
int
 
100
_hx509_request_set_SubjectPublicKeyInfo(hx509_context context,
 
101
                                        hx509_request req,
 
102
                                        const SubjectPublicKeyInfo *key)
 
103
{
 
104
    free_SubjectPublicKeyInfo(&req->key);
 
105
    return copy_SubjectPublicKeyInfo(key, &req->key);
 
106
}
 
107
 
 
108
int
 
109
_hx509_request_get_SubjectPublicKeyInfo(hx509_context context,
 
110
                                        hx509_request req,
 
111
                                        SubjectPublicKeyInfo *key)
 
112
{
 
113
    return copy_SubjectPublicKeyInfo(&req->key, key);
 
114
}
 
115
 
 
116
int
 
117
_hx509_request_add_eku(hx509_context context,
 
118
                       hx509_request req,
 
119
                       const heim_oid *oid)
 
120
{
 
121
    void *val;
 
122
    int ret;
 
123
 
 
124
    val = realloc(req->eku.val, sizeof(req->eku.val[0]) * (req->eku.len + 1));
 
125
    if (val == NULL)
 
126
        return ENOMEM;
 
127
    req->eku.val = val;
 
128
 
 
129
    ret = der_copy_oid(oid, &req->eku.val[req->eku.len]);
 
130
    if (ret)
 
131
        return ret;
 
132
 
 
133
    req->eku.len += 1;
 
134
 
 
135
    return 0;
 
136
}
 
137
 
 
138
int
 
139
_hx509_request_add_dns_name(hx509_context context,
 
140
                            hx509_request req,
 
141
                            const char *hostname)
 
142
{
 
143
    GeneralName name;
 
144
 
 
145
    memset(&name, 0, sizeof(name));
 
146
    name.element = choice_GeneralName_dNSName;
 
147
    name.u.dNSName = rk_UNCONST(hostname);
 
148
 
 
149
    return add_GeneralNames(&req->san, &name);
 
150
}
 
151
 
 
152
int
 
153
_hx509_request_add_email(hx509_context context,
 
154
                         hx509_request req,
 
155
                         const char *email)
 
156
{
 
157
    GeneralName name;
 
158
 
 
159
    memset(&name, 0, sizeof(name));
 
160
    name.element = choice_GeneralName_rfc822Name;
 
161
    name.u.dNSName = rk_UNCONST(email);
 
162
 
 
163
    return add_GeneralNames(&req->san, &name);
 
164
}
 
165
 
 
166
 
 
167
 
 
168
int
 
169
_hx509_request_to_pkcs10(hx509_context context,
 
170
                         const hx509_request req,
 
171
                         const hx509_private_key signer,
 
172
                         heim_octet_string *request)
 
173
{
 
174
    CertificationRequest r;
 
175
    heim_octet_string data, os;
 
176
    int ret;
 
177
    size_t size;
 
178
 
 
179
    if (req->name == NULL) {
 
180
        hx509_set_error_string(context, 0, EINVAL,
 
181
                               "PKCS10 needs to have a subject");
 
182
        return EINVAL;
 
183
    }
 
184
 
 
185
    memset(&r, 0, sizeof(r));
 
186
    memset(request, 0, sizeof(*request));
 
187
 
 
188
    r.certificationRequestInfo.version = pkcs10_v1;
 
189
 
 
190
    ret = copy_Name(&req->name->der_name,
 
191
                    &r.certificationRequestInfo.subject);
 
192
    if (ret)
 
193
        goto out;
 
194
    ret = copy_SubjectPublicKeyInfo(&req->key,
 
195
                                    &r.certificationRequestInfo.subjectPKInfo);
 
196
    if (ret)
 
197
        goto out;
 
198
    r.certificationRequestInfo.attributes =
 
199
        calloc(1, sizeof(*r.certificationRequestInfo.attributes));
 
200
    if (r.certificationRequestInfo.attributes == NULL) {
 
201
        ret = ENOMEM;
 
202
        goto out;
 
203
    }
 
204
 
 
205
    ASN1_MALLOC_ENCODE(CertificationRequestInfo, data.data, data.length,
 
206
                       &r.certificationRequestInfo, &size, ret);
 
207
    if (ret)
 
208
        goto out;
 
209
    if (data.length != size)
 
210
        abort();
 
211
 
 
212
    ret = _hx509_create_signature(context,
 
213
                                  signer,
 
214
                                  _hx509_crypto_default_sig_alg,
 
215
                                  &data,
 
216
                                  &r.signatureAlgorithm,
 
217
                                  &os);
 
218
    free(data.data);
 
219
    if (ret)
 
220
        goto out;
 
221
    r.signature.data = os.data;
 
222
    r.signature.length = os.length * 8;
 
223
 
 
224
    ASN1_MALLOC_ENCODE(CertificationRequest, data.data, data.length,
 
225
                       &r, &size, ret);
 
226
    if (ret)
 
227
        goto out;
 
228
    if (data.length != size)
 
229
        abort();
 
230
 
 
231
    *request = data;
 
232
 
 
233
out:
 
234
    free_CertificationRequest(&r);
 
235
 
 
236
    return ret;
 
237
}
 
238
 
 
239
int
 
240
_hx509_request_parse(hx509_context context,
 
241
                     const char *path,
 
242
                     hx509_request *req)
 
243
{
 
244
    CertificationRequest r;
 
245
    CertificationRequestInfo *rinfo;
 
246
    hx509_name subject;
 
247
    size_t len, size;
 
248
    void *p;
 
249
    int ret;
 
250
 
 
251
    if (strncmp(path, "PKCS10:", 7) != 0) {
 
252
        hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
 
253
                               "unsupport type in %s", path);
 
254
        return HX509_UNSUPPORTED_OPERATION;
 
255
    }
 
256
    path += 7;
 
257
 
 
258
    /* XXX PEM request */
 
259
 
 
260
    ret = rk_undumpdata(path, &p, &len);
 
261
    if (ret) {
 
262
        hx509_set_error_string(context, 0, ret, "Failed to map file %s", path);
 
263
        return ret;
 
264
    }
 
265
 
 
266
    ret = decode_CertificationRequest(p, len, &r, &size);
 
267
    rk_xfree(p);
 
268
    if (ret) {
 
269
        hx509_set_error_string(context, 0, ret, "Failed to decode %s", path);
 
270
        return ret;
 
271
    }
 
272
 
 
273
    ret = _hx509_request_init(context, req);
 
274
    if (ret) {
 
275
        free_CertificationRequest(&r);
 
276
        return ret;
 
277
    }
 
278
 
 
279
    rinfo = &r.certificationRequestInfo;
 
280
 
 
281
    ret = _hx509_request_set_SubjectPublicKeyInfo(context, *req,
 
282
                                                  &rinfo->subjectPKInfo);
 
283
    if (ret) {
 
284
        free_CertificationRequest(&r);
 
285
        _hx509_request_free(req);
 
286
        return ret;
 
287
    }
 
288
 
 
289
    ret = _hx509_name_from_Name(&rinfo->subject, &subject);
 
290
    if (ret) {
 
291
        free_CertificationRequest(&r);
 
292
        _hx509_request_free(req);
 
293
        return ret;
 
294
    }
 
295
    ret = _hx509_request_set_name(context, *req, subject);
 
296
    hx509_name_free(&subject);
 
297
    free_CertificationRequest(&r);
 
298
    if (ret) {
 
299
        _hx509_request_free(req);
 
300
        return ret;
 
301
    }
 
302
 
 
303
    return 0;
 
304
}
 
305
 
 
306
 
 
307
int
 
308
_hx509_request_print(hx509_context context, hx509_request req, FILE *f)
 
309
{
 
310
    int ret;
 
311
 
 
312
    if (req->name) {
 
313
        char *subject;
 
314
        ret = hx509_name_to_string(req->name, &subject);
 
315
        if (ret) {
 
316
            hx509_set_error_string(context, 0, ret, "Failed to print name");
 
317
            return ret;
 
318
        }
 
319
        fprintf(f, "name: %s\n", subject);
 
320
        free(subject);
 
321
    }
 
322
 
 
323
    return 0;
 
324
}
 
325