Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / libnfsidmap / gums.c
blob2b12d95208c2e59e3c0f04150dd0e95ad2308eb2
1 /*
2 * gums.c
4 * Copyright (c) 2004 The Regents of the University of Michigan.
5 * All rights reserved.
7 * Olga Kornievskaia <aglo@umich.edu>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #include <sys/types.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <pwd.h>
41 #include <grp.h>
42 #include <err.h>
43 #include <syslog.h>
44 #include "nfsidmap.h"
45 #include "nfsidmap_internal.h"
46 #include "cfg.h"
48 #include <voms_apic.h>
50 #include <prima_logger.h>
51 #include <prima_soap_client.h>
52 #include <prima_saml_support.h>
54 #define DEFAULT_PRIMA_CONF_LOCATION "/etc/grid-security/prima-authz.conf"
55 #define DEFAULT_VOMSDIR "/etc/grid-security/vomsdir"
56 #define DEFAULT_CADIR "/etc/grid-security/certificates"
57 #define X509_DN_SIZE 1024
59 //#define DEBUG_PRINT_VOMS
61 #define USING_TEST_PROGRAM
62 #ifdef USING_TEST_PROGRAM
63 nfs4_idmap_log_function_t idmap_log_func = printf;
64 int idmap_verbosity = 10;
65 #endif
68 * GUMS Translation Methods
72 /* global variables. voms/gums configuration attributes*/
73 static char prima_conf[] = DEFAULT_PRIMA_CONF_LOCATION;
74 typedef struct _plugin_config_params {
75 char *saml_schema_dir;
76 int saml_log_level;
77 char *server_cert;
78 char *server_key;
79 char *ca_dir;
80 char *gums_server_location;
81 char *voms_dir;
82 } plugin_config_params;
83 plugin_config_params conf;
85 #ifdef VOMS_BUG
86 static void my_VOMS_Delete(struct voms *v)
88 int i;
90 if (!v) return;
91 if (v->user)
92 free(v->user);
93 if (v->server)
94 free(v->server);
95 if (v->fqan) {
96 for (i = 0; v->fqan[i] != NULL; i++)
97 free(v->fqan[i]);
98 free(v->fqan);
100 free(v);
103 static struct voms *my_VOMS_Copy(struct voms *v, int *err)
105 struct voms *cv;
106 int i;
108 cv = calloc(1, sizeof(struct voms));
109 if (cv == NULL)
110 goto out;
111 cv->user = strdup(v->user);
112 if (cv->user == NULL)
113 goto out;
114 cv->server = strdup(v->server);
115 if (cv->server == NULL)
116 goto out;
117 for (i = 0; v->fqan[i] != NULL; i++) {
118 if (v->fqan[i] == NULL)
119 break;
121 cv->fqan = calloc(i+1, sizeof(char *));
122 if (cv->fqan == NULL)
123 goto out;
124 cv->fqan[i] = NULL;
125 for (i = 0; v->fqan[i] != NULL; i++) {
126 cv->fqan[i] = strdup(v->fqan[i]);
127 if (cv->fqan[i] == NULL)
128 goto out;
130 return cv;
131 out:
132 if (cv)
133 my_VOMS_Delete(cv);
135 return NULL;
137 #endif
140 #ifdef DEBUG_PRINT_VOMS
141 void printvoms(struct voms *v)
143 int j;
145 printf("SIGLEN: %d\nUSER: %s\n", v->siglen, v->user);
146 printf("UCA: %s\nSERVER: %s\n", v->userca, v->server);
147 printf("SCA: %s\nVO: %s\n", v->serverca, v->voname);
148 printf("URI: %s\nDATE1: %s\n", v->uri, v->date1);
149 printf("DATE2: %s\n", v->date2);
151 switch (v->type) {
152 case TYPE_NODATA:
153 printf("NO DATA\n");
154 break;
155 case TYPE_CUSTOM:
156 printf("%*s\n", v->datalen - 10, v->custom);
157 break;
158 case TYPE_STD:
159 j = 0;
160 while (v->std[j]) {
161 printf("GROUP: %s\nROLE: %s\nCAP: %s\n",v->std[j]->group,
162 v->std[j]->role,v->std[j]->cap);
163 j++;
168 void print(struct vomsdata *d)
170 struct voms **vo = d->data;
171 struct voms *v;
172 int k = 0;
174 while(vo[k]) {
175 v = vo[k++];
176 printf("%d *******************************************\n",k);
177 printvoms(v);
180 if (d->workvo)
181 printf("WORKVO: %s\n", d->workvo);
183 if (d->extra_data)
184 printf("EXTRA: %s\n", d->extra_data);
186 #endif
188 static void free_plugin_config_params()
190 if (conf.saml_schema_dir)
191 free(conf.saml_schema_dir);
192 conf.saml_schema_dir = NULL;
193 if (conf.server_cert)
194 free(conf.server_cert);
195 conf.server_cert = NULL;
196 if (conf.server_key)
197 free(conf.server_key);
198 conf.server_key = NULL;
199 if (conf.ca_dir)
200 free(conf.ca_dir);
201 conf.ca_dir = NULL;
202 if (conf.voms_dir)
203 free(conf.voms_dir);
204 conf.voms_dir = NULL;
207 static int validate_plugin_config_params()
209 if (conf.saml_schema_dir == NULL ||
210 conf.server_cert == NULL ||
211 conf.server_key == NULL ||
212 conf.gums_server_location == NULL)
213 return -1;
215 if (conf.ca_dir == NULL) {
216 conf.ca_dir = strdup(DEFAULT_CADIR);
217 if (conf.ca_dir == NULL)
218 return -1;
220 if (conf.voms_dir == NULL) {
221 conf.voms_dir = strdup(DEFAULT_VOMSDIR);
222 if (conf.voms_dir == NULL)
223 return -1;
225 return 0;
228 static int gums_init(void)
230 FILE *f = NULL;
231 int ret = -1, i = 0;
232 char buf[512], type[128], value[256];
233 char *alt_conf = NULL;
235 alt_conf = conf_get_str("GUMS", "Conf_File");
236 if (alt_conf == NULL)
237 f = fopen(prima_conf, "r");
238 else
239 f = fopen(alt_conf, "r");
240 if (f == NULL)
241 goto out;
243 while (fgets(buf, 512, f)) {
244 i = 0;
245 while(buf[i] == ' ' || buf[i] == '\t')
246 i++;
247 if (buf[i] == '#' || buf[i] == '\0' || buf[i] == '\n')
248 continue;
249 if (sscanf(&buf[i], "%127s%255s",type,value) < 2) {
250 IDMAP_LOG(0, ("ERROR: malformed line: %s\n", &buf[i]));
251 goto out;
253 IDMAP_LOG(1, ("PRIMA conf: type=%s value=%s\n", type, value));
254 if (strncmp(type, "imsContact", 10) == 0) {
255 conf.gums_server_location = strdup(value);
256 } else if (strncmp(type, "serviceCert", 11) == 0) {
257 conf.server_cert = strdup(value);
258 } else if (strncmp(type, "serviceKey", 10) == 0) {
259 conf.server_key = strdup(value);
260 } else if (strncmp(type, "caCertDir", 9) == 0) {
261 conf.ca_dir = strdup(value);
262 } else if (strncmp(type, "samlSchemaDir", 13) == 0) {
263 conf.saml_schema_dir = strdup(value);
264 } else if (strncmp(type, "logLevel", 8) == 0) {
265 if (strncmp(value, "debug", 5) == 0)
266 conf.saml_log_level = PRIMA_LOG_DEBUG;
267 else if (strncmp(value, "error", 5) == 0)
268 conf.saml_log_level = PRIMA_LOG_ERROR;
269 else if (strncmp(value, "none", 4) == 0)
270 conf.saml_log_level = PRIMA_LOG_NONE;
271 else
272 conf.saml_log_level = PRIMA_LOG_INFO;
276 if (validate_plugin_config_params() != 0)
277 goto out;
279 ret = 0;
280 out:
281 if (f)
282 fclose(f);
283 if (ret)
284 free_plugin_config_params();
286 return ret;
289 static int retrieve_attributes(X509 *cert, STACK_OF(X509) *cas,
290 struct voms **attrs)
292 int ret = -1, err = 0;
293 struct vomsdata *vd = NULL;
295 vd = VOMS_Init(conf.voms_dir, conf.ca_dir);
296 if (vd == NULL) {
297 IDMAP_LOG(0, ("VOMS_Init failed\n"));
298 return -1;
300 ret = VOMS_Retrieve(cert, cas, RECURSE_CHAIN, vd, &err);
301 if (err) {
302 char *err_msg;
303 err_msg = VOMS_ErrorMessage(vd, err, NULL, 0);
304 if (err == VERR_NOEXT)
305 ret = 0;
306 else
307 IDMAP_LOG(0, ("VOMS error %s\n", err_msg));
308 goto out;
309 } else if (ret) {
310 struct voms *v, *v2;
311 #ifdef DEBUG_PRINT_VOMS
312 print(vd);
313 #endif
314 v = VOMS_DefaultData(vd, &err);
315 if (err == VERR_NONE) {
316 #ifdef DEBUG_PRINT_VOMS
317 printvoms(v);
318 while (v->fqan[i] != NULL)
319 IDMAP_LOG(1, ("user's fqan: %s\n", v->fqan[i++]));
320 #endif
321 #ifdef VOMS_BUG
322 v2 = my_VOMS_Copy(v, &err);
323 #else
324 v2 = VOMS_Copy(v, &err);
325 #endif
326 if (v2 == NULL) {
327 IDMAP_LOG(0, ("VOMS_Copy failed err=%d\n", err));
328 goto out;
330 *attrs = v2;
333 ret = 0;
334 out:
335 if (vd)
336 VOMS_Destroy(vd);
337 return ret;
340 static int get_server_dn(unsigned char **server_dn)
342 BIO *tmp = NULL;
343 X509 *cert = NULL;
344 int ret = -1;
345 char dn[X509_DN_SIZE];
347 tmp = BIO_new(BIO_s_file());
348 if (tmp == NULL)
349 goto out;
351 ret = BIO_read_filename(tmp, conf.server_cert);
352 if (ret == 0) {
353 ret = errno;
354 goto out;
357 cert = (X509 *) PEM_read_bio_X509(tmp, NULL, NULL, NULL);
358 if (cert == NULL)
359 goto out;
361 X509_NAME_oneline(X509_get_subject_name(cert), dn, sizeof(dn));
363 *server_dn = strdup(dn);
364 if (*server_dn == NULL)
365 goto out;
367 ret = 0;
368 out:
369 if (tmp)
370 BIO_free(tmp);
371 if (cert)
372 X509_free(cert);
374 return ret;
377 static int create_saml_request(char *dn, struct voms *attrs, char **saml_req)
379 int ret = -1, i;
380 char *req = NULL;
381 unsigned char *server_dn = NULL;
382 prima_saml_fqans fqans;
384 IDMAP_LOG(2, ("create_saml_request start\n"));
385 ret = initPrimaSAMLFQANs(&fqans);
386 if (ret) {
387 IDMAP_LOG(0, ("initPrimaSAMLFQANs failed with %d\n", ret));
388 goto out;
391 if (attrs) {
392 for (i = 0; attrs->fqan[i] != NULL; i++) {
393 ret = addPrimaSAMLFQAN(&fqans, attrs->server, attrs->fqan[i]);
394 IDMAP_LOG(1, ("addPrimaSAMLFQAN returned %d\n", ret));
396 dn = attrs->user;
397 } else
398 IDMAP_LOG(1, ("No VOMS attributes present in the cert\n"));
400 if (get_server_dn(&server_dn) != 0)
401 goto out;
402 req = createSAMLQueryAndRequest(server_dn, dn, &fqans);
403 if (req == NULL) {
404 IDMAP_LOG(0, ("createSAMLQueryAndRequest failed to create "
405 "SAML request\n"));
406 goto out;
408 IDMAP_LOG(1, ("SAML Request %s\n", req));
410 ret = 0;
411 *saml_req = req;
412 out:
413 cleanupPrimaSAMLFQANs(&fqans);
415 if (server_dn)
416 free(server_dn);
418 IDMAP_LOG(2, ("create_saml_request returning %d\n", ret));
419 return ret;
422 static int process_parameters(extra_mapping_params **ex, X509 **user_cert,
423 STACK_OF(X509) **user_chain)
426 int ret = -1, i;
427 X509 *cert = NULL, *x;
428 STACK_OF(X509) *chain = NULL;
429 unsigned char *p;
431 if (ex[0]->content_type != X509_CERT)
432 return -1;
434 /* get user's x509 certificate */
435 p = ex[0]->content;
436 cert = d2i_X509(NULL, &p, ex[0]->content_len);
437 if (cert == NULL)
438 goto out;
440 /* get user's other certificates */
441 chain = sk_X509_new_null();
442 if (chain == NULL)
443 goto out;
444 for (i = 1; ex[i] != NULL; i++) {
445 if (ex[i]->content_type != X509_CERT)
446 continue;
447 p = ex[i]->content;
448 x = d2i_X509(NULL, &p, ex[i]->content_len);
449 if (x == NULL)
450 goto out;
451 sk_X509_push(chain, x);
453 ret = 0;
455 *user_cert = cert;
456 *user_chain = chain;
457 out:
458 if (ret) {
459 int num;
460 if (cert)
461 X509_free(cert);
462 if (chain)
463 sk_X509_pop_free(chain, X509_free);
466 return ret;
469 struct pwbuf {
470 struct passwd pwbuf;
471 char buf[1];
474 static int translate_to_uid(char *local_uid, uid_t *uid, uid_t *gid)
476 int ret = -1;
477 struct passwd *pw = NULL;
478 struct pwbuf *buf = NULL;
479 size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
481 buf = malloc(sizeof(*buf) + buflen);
482 if (buf == NULL)
483 goto out;
485 ret = getpwnam_r(local_uid, &buf->pwbuf, buf->buf, buflen, &pw);
486 if (pw == NULL) {
487 IDMAP_LOG(0, ("getpwnam: name %s not found\n", local_uid));
488 goto out;
490 *uid = pw->pw_uid;
491 *gid = pw->pw_gid;
493 ret = 0;
494 out:
495 if (buf)
496 free(buf);
497 return ret;
500 static int translate_to_gid(char *local_gid, uid_t *gid)
502 struct group *gr = NULL;
503 struct group grbuf;
504 char *buf = NULL;
505 size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
506 int ret = -1;
508 do {
509 buf = malloc(buflen);
510 if (buf == NULL)
511 goto out;
513 ret = -getgrnam_r(local_gid, &grbuf, buf, buflen, &gr);
514 if (gr == NULL && !ret)
515 ret = -ENOENT;
516 if (ret == -ERANGE) {
517 buflen *= 2;
518 free(buf);
520 } while (ret == -ERANGE);
522 if (ret)
523 goto out;
525 *gid = gr->gr_gid;
527 ret = 0;
528 out:
529 if (buf)
530 free(buf);
531 return ret;
534 static int gums_gss_princ_to_ids(char *secname, char *princ,
535 uid_t *uid, uid_t *gid,
536 extra_mapping_params **ex)
538 int ret = -1, size, i;
539 X509 *cert = NULL;
540 STACK_OF(X509) *cas = NULL;
541 char dn[X509_DN_SIZE];
542 struct voms *attrs = NULL;
543 char *saml_req = NULL, *saml_resp = NULL;
544 int saml_result;
545 char *local_uid = NULL, *local_gid = NULL, *p;
547 /* accept only spkm3 translations */
548 if (strcmp(secname, "spkm3"))
549 return -EINVAL;
551 /* must supply either a DN and/or at least 1 binary blob */
552 if (princ == NULL && (ex == NULL || (ex && ex[0] == NULL)))
553 return -EINVAL;
555 /* process extra parameters */
556 if (process_parameters(ex, &cert, &cas) != 0)
557 goto out;
559 IDMAP_LOG(1, ("Processing name translation of client\n"));
560 X509_NAME_oneline(X509_get_subject_name(cert), dn, sizeof(dn));
561 IDMAP_LOG(1, ("DN=%s\n", dn));
562 size = sk_X509_num(cas);
563 IDMAP_LOG(1, ("Including following CAs (%d)\n", size));
564 for (i=0; i < size; i++) {
565 X509_NAME_oneline(X509_get_subject_name(sk_X509_value(cas, i)),
566 dn, sizeof(dn));
567 IDMAP_LOG(1, ("DN=%s\n", dn));
570 /* retrieve VOMS attributes */
571 if (retrieve_attributes(cert, cas, &attrs) != 0)
572 goto out;
573 if (attrs == NULL)
574 X509_NAME_oneline(X509_get_subject_name(cert), dn, sizeof(dn));
576 /* initialize SAML library */
577 if (initPrimaSAMLSupport(conf.saml_schema_dir,
578 conf.saml_log_level) != 0) {
579 IDMAP_LOG(0, ("initPrimaSAMLSupport failed\n"));
580 goto out;
583 /* create SAML request */
584 if (create_saml_request(dn, attrs, &saml_req) != 0)
585 goto out;
587 /* contact GUMS server */
588 saml_resp = queryIdentityMappingService(conf.gums_server_location,
589 saml_req, conf.server_cert, conf.server_key,
590 conf.ca_dir);
591 if (saml_resp != NULL) {
592 saml_result = processResponse(saml_resp, saml_req, &local_uid,
593 &local_gid);
594 IDMAP_LOG(1, ("processResponse returned %d\n", saml_result));
595 if (saml_result || local_uid == NULL) {
596 IDMAP_LOG(0, ("processResponse failed to return "
597 "local id\n"));
598 ret = -ENOENT;
599 goto out;
601 IDMAP_LOG(1, ("GUMS returned uid=%s gid=%s\n", local_uid,
602 local_gid));
605 /* translate account name to uid */
606 if (translate_to_uid(local_uid, uid, gid))
607 goto out;
608 if (local_gid)
609 if (translate_to_gid(local_gid, gid))
610 goto out;
612 ret = 0;
613 out:
614 if (cert)
615 X509_free(cert);
617 if (cas)
618 sk_X509_pop_free(cas, X509_free);
620 if (attrs)
621 #ifdef VOMS_BUG
622 my_VOMS_Delete(attrs);
623 #else
624 VOMS_Delete(attrs);
625 #endif
627 if (saml_req)
628 free(saml_req);
630 if (saml_resp)
631 free(saml_resp);
633 cleanupPrimaSAMLSupport();
635 return ret;
638 struct trans_func gums_trans = {
639 .name = "gums",
640 .init = gums_init,
641 .princ_to_ids = gums_gss_princ_to_ids,
642 .name_to_uid = NULL,
643 .name_to_gid = NULL,
644 .uid_to_name = NULL,
645 .gid_to_name = NULL,
646 .gss_princ_to_grouplist = NULL,
649 struct trans_func *libnfsidmap_plugin_init()
651 return (&gums_trans);
654 #ifdef USING_TEST_PROGRAM
655 static STACK_OF(X509) *load_chain(char *certfile)
657 STACK_OF(X509_INFO) *sk=NULL;
658 STACK_OF(X509) *stack=NULL, *ret=NULL;
659 BIO *in=NULL;
660 X509_INFO *xi;
661 int first = 1;
663 if (!(stack = sk_X509_new_null())) {
664 printf("memory allocation failure\n");
665 goto end;
668 if (!(in=BIO_new_file(certfile, "r"))) {
669 printf("error opening the file, %s\n",certfile);
670 goto end;
673 /* This loads from a file, a stack of x509/crl/pkey sets */
674 if (!(sk=(STACK_OF(X509_INFO) *)PEM_X509_INFO_read_bio(in,NULL,NULL,NULL))) {
675 /* if (!(sk=PEM_X509_read_bio(in,NULL,NULL,NULL))) { */
676 printf("error reading the file, %s\n",certfile);
677 goto end;
680 /* scan over it and pull out the certs */
681 while (sk_X509_INFO_num(sk)) {
682 /* skip first cert */
683 if (first) {
684 xi=sk_X509_INFO_shift(sk);
685 X509_INFO_free(xi);
686 first = 0;
687 continue;
689 xi=sk_X509_INFO_shift(sk);
690 if (xi->x509 != NULL) {
691 sk_X509_push(stack,xi->x509);
692 xi->x509=NULL;
694 X509_INFO_free(xi);
696 if (!sk_X509_num(stack)) {
697 printf("no certificates in file, %s\n",certfile);
698 sk_X509_free(stack);
699 goto end;
701 ret=stack;
702 end:
703 BIO_free(in);
704 sk_X509_INFO_free(sk);
705 return(ret);
708 void create_params(X509 *cert, STACK_OF(X509) *cas,
709 extra_mapping_params ***ret_params)
711 int len = 0, i, size = 0;
712 unsigned char *p, *buf = NULL;
713 extra_mapping_params **params = NULL;
714 X509 *x;
716 if (cas)
717 size = sk_X509_num(cas);
718 params = malloc((size+2)*sizeof(extra_mapping_params *));
719 params[size+1] = NULL;
721 /* 1st element is user's certificate */
722 len = i2d_X509(cert, NULL);
723 p = buf = malloc(len);
724 i2d_X509(cert, &p);
725 params[0] = malloc(sizeof(extra_mapping_params));
726 params[0]->content_type = X509_CERT;
727 params[0]->content = buf;
728 params[0]->content_len = len;
730 /* add other certificates to the array */
731 for (i = 0; i < size; i++) {
732 x = sk_X509_value(cas, i);
733 params[i+1] = malloc(sizeof(extra_mapping_params));
734 len = i2d_X509(x, NULL);
735 p = buf = malloc(len);
736 i2d_X509(x, &p);
737 params[i+1]->content_type = X509_CERT;
738 params[i+1]->content = buf;
739 params[i+1]->content_len = len;
741 *ret_params = params;
744 int main(void)
746 int uid, gid, ret, i;
747 extra_mapping_params **params = NULL;
748 BIO *tmp = NULL;
749 X509 *cert = NULL, *x;
750 STACK_OF(X509) *cas = NULL;
751 unsigned char *proxy_file;
753 if (gums_init())
754 return -1;
755 proxy_file = getenv("X509_USER_PROXY");
756 if (proxy_file == NULL) {
757 fprintf(stderr, "X509_USER_PROXY is not set\n");
758 return -1;
760 tmp = BIO_new(BIO_s_file());
761 BIO_read_filename(tmp, proxy_file);
762 cert = (X509 *) PEM_read_bio_X509(tmp, NULL, NULL, NULL);
763 cas = load_chain(proxy_file);
764 create_params(cert, cas, &params);
765 ret = gums_gss_princ_to_ids("spkm3", NULL, &uid, &gid, params);
766 fprintf(stderr, "gums_gss_princ_to_ids returns %d uid=%d gid=%d\n",
767 ret, uid, gid);
769 if (tmp)
770 BIO_free(tmp);
771 if (cert)
772 X509_free(cert);
773 if (cas)
774 sk_X509_pop_free(cas, X509_free);
776 free_plugin_config_params();
778 if (params) {
779 for (i=0; params[i] != NULL; i++) {
780 free(params[i]->content);
781 free(params[i]);
783 free(params);
786 return 0;
788 #endif