1 /*
2  * Portions of this file Copyright 1999-2005 University of Chicago
3  * Portions of this file Copyright 1999-2005 The University of Southern California.
4  *
5  * This file or a portion of this file is licensed under the
6  * terms of the Globus Toolkit Public License, found at
7  * http://www.globus.org/toolkit/download/license.html.
8  * If you redistribute this file, with or without
9  * modifications, you must include this notice in the file.
10  */
11
12
13 #include "globus_ws_security.h"
14 #include "globus_i_ws_security.h"
15
16 globus_result_t
17 globus_ws_security_create_pkipath(
18     globus_gsi_cred_handle_t            cred,
19     char **                             encoded_buffer,
20     int *                               encoded_length)
21 0 {
22 0     globus_result_t                     result = GLOBUS_SUCCESS;
23 0     STACK_OF(X509) *                    chain = NULL;
24 0     X509 *                              cert = NULL;
25 0     unsigned char *                     pack_buff = NULL;
26 0     int                                 pack_buff_length = 0;
27 0     char *                              pkipath_buff = NULL;
28 0     int                                 pkipath_length = 0;
29 0     BIO *                               b64;
30 0     BIO *                               mem;
31 0     BIO *                               bio;
32 0     BUF_MEM *                           bm;
33 0     STACK_OF(X509) *                    pkipath_stack = NULL;
34 0     GlobusFuncName(globus_ws_security_create_pkipath);
35 0     GlobusWSSecurityDebugEnter();
36
37 0     result = globus_gsi_cred_get_cert_chain(cred, &chain);
38 0     if(result != GLOBUS_SUCCESS)
39     {
40 0         result = GlobusWSSecurityErrorCreatingPKIPath(
41             result, "Failed to get cert chain from credential");
42 0         goto exit;
43     }
44
45 0     pkipath_stack = sk_X509_new_null();
46     
47 0     while(sk_X509_num(chain) > 0)
48     {
49 0         sk_X509_push(pkipath_stack, sk_X509_pop(chain));
50     }
51
52 0     sk_X509_free(chain);
53
54 0     result = globus_gsi_cred_get_cert(
55         cred, &cert);
56 0     if(result != GLOBUS_SUCCESS)
57     {
58 0         result = GlobusWSSecurityErrorCreatingPKIPath(
59             result, "Failed to get certificate from credential");
60 0         goto free_stack;
61     }
62
63 0     sk_X509_push(pkipath_stack, (char *)cert);
64     
65 0     pack_buff = ASN1_seq_pack(
66         pkipath_stack, i2d_X509, &pack_buff, &pack_buff_length);
67 0     if(!pack_buff)
68     {
69 0         result = GlobusWSSecurityErrorCreatingPKIPath(
70             result, 
71             "Failed to pack certificates"
72             " into DER encoded ASN1 sequence");
73 0         goto free_stack;
74     }
75
76 0     b64 = BIO_new(BIO_f_base64());
77 0     mem = BIO_new(BIO_s_mem());
78 0     bio = BIO_push(b64, mem);
79
80 0     if(BIO_write(bio, pack_buff, pack_buff_length) <= 0)
81     {
82 0         result = GlobusWSSecurityErrorOpenSSL(
83             "Failed to base64 encode DER sequence");
84 0         goto free_bio;
85     }
86     
87 0     if(BIO_flush(bio) <= 0)
88     {
89 0         result = GlobusWSSecurityErrorOpenSSL(
90             "Failed to flush base64 encoding BIO");
91 0         goto free_bio;
92     }
93
94 0     BIO_get_mem_ptr(bio, &bm);
95     
96 0     pkipath_buff = globus_malloc(bm->length + 1);
97 0     pkipath_length = bm->length;
98 0     memcpy(pkipath_buff, bm->data, pkipath_length);
99 0     pkipath_buff[pkipath_length] = '\0';
100
101 0     GlobusWSSecurityDebugPrintf(
102         GLOBUS_L_WS_SECURITY_DEBUG_PKIPATH, 
103         ("============== ENCODED PKI PATH BUFFER ============= (size: %d)"
104          "\n%*s\n"
105          "----------------------------------------------------\n", 
106          pkipath_length, pkipath_length, pkipath_buff));
107     
108 0     *encoded_buffer = pkipath_buff;
109 0     *encoded_length = pkipath_length;
110     
111  free_bio:
112     
113 0     BIO_free_all(bio);
114
115 /*  free_pack_buff: */
116
117 0     OPENSSL_free(pack_buff);
118
119  free_stack:
120
121 0     sk_X509_pop_free(pkipath_stack, X509_free);
122
123 /*  free_cert: */
124 /*     X509_free(cert); */
125
126  exit:
127     
128 0     GlobusWSSecurityDebugExit();
129 0     return result;
130 }
131
132 globus_result_t
133 globus_ws_security_get_credential(
134     const unsigned char *               encoded_buff,
135     int                                 encoded_length,
136     globus_gsi_cred_handle_t *          new_cred)
137 0 {
138 0     globus_result_t                     result = GLOBUS_SUCCESS;
139 0     unsigned char *                     dec;
140 0     int                                 length;
141 0     BIO *                               b64;
142 0     BIO *                               mem;
143 0     BIO *                               bio;
144 0     STACK_OF(X509) *                    pkipath_stack;
145 0     STACK_OF(X509) *                    chain;
146 0     X509 *                              user_cert;
147 0     globus_gsi_cred_handle_t            cred;
148 0     GlobusFuncName(globus_ws_security_get_credential);
149 0     GlobusWSSecurityDebugEnter();
150
151 0     b64 = BIO_new(BIO_f_base64());
152 0     mem = BIO_new_mem_buf((unsigned char *)encoded_buff, encoded_length);
153 0     bio = BIO_push(b64, mem);
154
155 0     length = BIO_pending(bio);
156 0     dec = globus_malloc(length);
157 0     if(!dec)
158     {
159 0         result = GlobusWSSecurityErrorOutOfMemory(length);
160 0         goto free_bio;
161     }
162
163 0     length = BIO_read(bio, dec, length);
164 0     pkipath_stack = ASN1_seq_unpack(dec, length,
165                                     (char *(*)())d2i_X509,
166                                     (void (*)(void *))X509_free);
167 0     if(!pkipath_stack)
168     {
169 0         result = GlobusWSSecurityErrorOpenSSL(
170             "Could not unpack the DER encoded PKI path"
171             "buffer into a stack of X509 certificates");
172 0         goto free_dec;
173     }
174     
175 0     user_cert = sk_X509_pop(pkipath_stack);
176
177 0     result = globus_gsi_cred_handle_init(&cred, NULL);
178 0     if(result != GLOBUS_SUCCESS)
179     {
180 0         result = GlobusWSSecurityErrorImportingCredential(
181             result, "can't create handle for credential");
182 0         goto free_stack;
183     }
184
185 0     result = globus_gsi_cred_set_cert(cred, user_cert);
186 0     if(result != GLOBUS_SUCCESS)
187     {
188 0         result = GlobusWSSecurityErrorImportingCredential(
189             result, "can't set certificate in credential handle");
190 0         goto free_cred;
191     }
192
193     /* reverse stack for chain */
194 0     chain = sk_X509_new_null();
195 0     while(sk_X509_num(pkipath_stack) > 0)
196     {
197 0         sk_X509_push(chain, sk_X509_pop(pkipath_stack));
198     }
199         
200 0     result = globus_gsi_cred_set_cert_chain(cred, chain);
201 0     if(result != GLOBUS_SUCCESS)
202     {
203 0         result = GlobusWSSecurityErrorImportingCredential(
204             result, "can't set certificate chain in credential handle");
205 0         goto free_cred;
206     }
207
208 0     *new_cred = cred;
209
210 0     goto free_stack;
211
212  free_cred:
213
214 0     globus_gsi_cred_handle_destroy(cred);
215
216  free_stack:
217
218 0     sk_X509_pop_free(pkipath_stack, X509_free);
219
220 /* free chain */
221
222 0     sk_X509_pop_free(chain, X509_free);
223
224 /*  free_cert: */
225
226 0     X509_free(user_cert);
227
228  free_dec:
229
230 0     globus_free(dec);
231
232  free_bio:
233
234 0     BIO_free_all(bio);
235
236 /* exit:*/
237
238 0     GlobusWSSecurityDebugExit();
239 0     return result;