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