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 BIO * b64;
35 BIO * mem;
36 BIO * bio;
37 BUF_MEM * bm;
38 0 STACK_OF(X509) * pkipath_stack = NULL;
39 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 0 free_bio:
117
118 0 BIO_free_all(bio);
119
120 /* free_pack_buff: */
121
122 0 OPENSSL_free(pack_buff);
123
124 0 free_stack:
125
126 0 sk_X509_pop_free(pkipath_stack, X509_free);
127
128 /* free_cert: */
129 /* X509_free(cert); */
130
131 0 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 unsigned char * dec;
145 int length;
146 BIO * b64;
147 BIO * mem;
148 BIO * bio;
149 STACK_OF(X509) * pkipath_stack;
150 STACK_OF(X509) * chain;
151 X509 * user_cert;
152 globus_gsi_cred_handle_t cred;
153 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 0 free_cred:
218
219 0 globus_gsi_cred_handle_destroy(cred);
220
221 0 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 0 free_dec:
234
235 0 globus_free(dec);
236
237 0 free_bio:
238
239 0 BIO_free_all(bio);
240
241 /* exit:*/
242
243 0 GlobusWSSecurityDebugExit();
244 0 return result;