int main(){ // called at the start of shell, manages all other shell commands printf("\nWelcome to GoodShell!\nTotally not a ripoff of Bash.\n\n"); chdir(home() ); char input[MAX_INPUT]; char **cmds, **cmd_p, **args; while(1){ // new line with path for new command print_prompt(); // gets the command line argument read_line(input); // seperates commands cmds = separate_cmds(input); if (cmds){ for (cmd_p = cmds; *cmd_p; cmd_p++){ args = separate_args(*cmd_p); if (args){ exec_cmd(args, cmds); free_strlist(args); } } free_strlist(cmds); } } return EXIT_FAILURE; }
int keyserver_export (ctrl_t ctrl, strlist_t users) { gpg_error_t err; strlist_t sl=NULL; KEYDB_SEARCH_DESC desc; int rc=0; /* Weed out descriptors that we don't support sending */ for(;users;users=users->next) { err = classify_user_id (users->d, &desc, 1); if (err || (desc.mode != KEYDB_SEARCH_MODE_SHORT_KID && desc.mode != KEYDB_SEARCH_MODE_LONG_KID && desc.mode != KEYDB_SEARCH_MODE_FPR16 && desc.mode != KEYDB_SEARCH_MODE_FPR20)) { log_error(_("\"%s\" not a key ID: skipping\n"),users->d); continue; } else append_to_strlist(&sl,users->d); } if(sl) { rc = keyserver_put (ctrl, sl, opt.keyserver); free_strlist(sl); } return rc; }
void curl_slist_free_all(struct curl_slist *list) { if(list) { free_strlist(list->list); free(list); } }
static gpg_error_t cmd_delkeys (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); char *p; strlist_t list, sl; int rc; /* break the line down into an strlist_t */ list = NULL; for (p=line; *p; line = p) { while (*p && *p != ' ') p++; if (*p) *p++ = 0; if (*line) { sl = xtrymalloc (sizeof *sl + strlen (line)); if (!sl) { free_strlist (list); return out_of_core (); } sl->flags = 0; strcpy_escaped_plus (sl->d, line); sl->next = list; list = sl; } } rc = gpgsm_delete (ctrl, list); free_strlist (list); /* close and reset the fd */ close_message_fd (ctrl); assuan_close_input_fd (ctx); assuan_close_output_fd (ctx); return rc; }
void free_keyserver_spec(struct keyserver_spec *keyserver) { xfree(keyserver->uri); xfree(keyserver->scheme); xfree(keyserver->auth); xfree(keyserver->host); xfree(keyserver->port); xfree(keyserver->path); xfree(keyserver->opaque); free_strlist(keyserver->options); xfree(keyserver); }
/* Import all keys that match name */ int keyserver_import_name (ctrl_t ctrl, const char *name, unsigned char **fpr, size_t *fpr_len, struct keyserver_spec *keyserver) { strlist_t list=NULL; int rc; append_to_strlist(&list,name); rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED); /* FIXME */ /* keyserver_work (ctrl, KS_GETNAME, list, NULL, */ /* 0, fpr, fpr_len, keyserver); */ free_strlist(list); return rc; }
int verify_signatures (ctrl_t ctrl, int nfiles, char **files ) { IOBUF fp; armor_filter_context_t *afx = NULL; progress_filter_context_t *pfx = new_progress_context (); const char *sigfile; int i, rc; strlist_t sl; /* Decide whether we should handle a detached or a normal signature, * which is needed so that the code later can hash the correct data and * not have a normal signature act as detached signature and ignoring the * indended signed material from the 2nd file or stdin. * 1. gpg <file - normal * 2. gpg file - normal (or detached) * 3. gpg file <file2 - detached * 4. gpg file file2 - detached * The question is how decide between case 2 and 3? The only way * we can do it is by reading one byte from stdin and then unget * it; the problem here is that we may be reading from the * terminal (which could be detected using isatty() but won't work * when under contol of a pty using program (e.g. expect)) and * might get us in trouble when stdin is used for another purpose * (--passphrase-fd 0). So we have to break with the behaviour * prior to gpg 1.0.4 by assuming that case 3 is a normal * signature (where file2 is ignored and require for a detached * signature to indicate signed material comes from stdin by using * case 4 with a file2 of "-". * * Actually we don't have to change anything here but can handle * that all quite easily in mainproc.c */ sigfile = nfiles? *files : NULL; /* open the signature file */ fp = iobuf_open(sigfile); if (fp && is_secured_file (iobuf_get_fd (fp))) { iobuf_close (fp); fp = NULL; gpg_err_set_errno (EPERM); } if( !fp ) { rc = gpg_error_from_syserror (); log_error(_("can't open '%s': %s\n"), print_fname_stdin(sigfile), gpg_strerror (rc)); goto leave; } handle_progress (pfx, fp, sigfile); if ( !opt.no_armor && use_armor_filter( fp ) ) { afx = new_armor_context (); push_armor_filter (afx, fp); } sl = NULL; for(i=nfiles-1 ; i > 0 ; i-- ) add_to_strlist( &sl, files[i] ); rc = proc_signature_packets (ctrl, NULL, fp, sl, sigfile ); free_strlist(sl); iobuf_close(fp); if( (afx && afx->no_openpgp_data && rc == -1) || rc == G10ERR_NO_DATA ) { log_error(_("the signature could not be verified.\n" "Please remember that the signature file (.sig or .asc)\n" "should be the first file given on the command line.\n") ); rc = 0; } leave: release_armor_context (afx); release_progress_context (pfx); return rc; }
/* This is the central function to collect the keys for recipients. It is thus used to prepare a public key encryption. encrypt-to keys, default keys and the keys for the actual recipients are all collected here. When not in batch mode and no recipient has been passed on the commandline, the function will also ask for recipients. RCPTS is a string list with the recipients; NULL is an allowed value but not very useful. Group expansion is done on these names; they may be in any of the user Id formats we can handle. The flags bits for each string in the string list are used for: Bit 0: This is an encrypt-to recipient. Bit 1: This is a hidden recipient. USE is the desired use for the key - usually PUBKEY_USAGE_ENC. RET_PK_LIST. On success a list of keys is stored at the address RET_PK_LIST; the caller must free this list. On error the value at this address is not changed. */ int build_pk_list( STRLIST rcpts, PK_LIST *ret_pk_list, unsigned int use ) { PK_LIST pk_list = NULL; PKT_public_key *pk=NULL; int rc=0; int any_recipients=0; STRLIST rov,remusr; char *def_rec = NULL; /* Try to expand groups if any have been defined. */ if (opt.grouplist) remusr = expand_group (rcpts); else remusr = rcpts; /* Check whether there are any recipients in the list and build the * list of the encrypt-to ones (we always trust them). */ for ( rov = remusr; rov; rov = rov->next ) { if ( !(rov->flags & 1) ) { /* This is a regular recipient; i.e. not an encrypt-to one. */ any_recipients = 1; /* Hidden recipients are not allowed while in PGP mode, issue a warning and switch into GnuPG mode. */ if ((rov->flags&2) && (PGP2 || PGP6 || PGP7 || PGP8)) { log_info(_("you may not use %s while in %s mode\n"), "--hidden-recipient", compliance_option_string()); compliance_failure(); } } else if ( (use & PUBKEY_USAGE_ENC) && !opt.no_encrypt_to ) { /* Encryption has been requested and --encrypt-to has not been disabled. Check this encrypt-to key. */ pk = xmalloc_clear( sizeof *pk ); pk->req_usage = use; /* We explicitly allow encrypt-to to an disabled key; thus we pass 1 as last argument. */ if ( (rc = get_pubkey_byname ( pk, rov->d, NULL, NULL, 1 )) ) { free_public_key ( pk ); pk = NULL; log_error (_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); write_status_text_and_buffer (STATUS_INV_RECP, "0 ", rov->d, strlen (rov->d), -1); goto fail; } else if ( !(rc=check_pubkey_algo2 (pk->pubkey_algo, use )) ) { /* Skip the actual key if the key is already present * in the list. Add it to our list if not. */ if (key_present_in_pk_list(pk_list, pk) == 0) { free_public_key (pk); pk = NULL; log_info (_("%s: skipped: public key already present\n"), rov->d); } else { PK_LIST r; r = xmalloc( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = (rov->flags&2)?1:0; pk_list = r; /* Hidden encrypt-to recipients are not allowed while in PGP mode, issue a warning and switch into GnuPG mode. */ if ((r->flags&1) && (PGP2 || PGP6 || PGP7 || PGP8)) { log_info(_("you may not use %s while in %s mode\n"), "--hidden-encrypt-to", compliance_option_string()); compliance_failure(); } } } else { /* The public key is not usable for encryption or not available. */ free_public_key( pk ); pk = NULL; log_error(_("%s: skipped: %s\n"), rov->d, g10_errstr(rc) ); write_status_text_and_buffer (STATUS_INV_RECP, "0 ", rov->d, strlen (rov->d), -1); goto fail; } } } /* If we don't have any recipients yet and we are not in batch mode drop into interactive selection mode. */ if ( !any_recipients && !opt.batch ) { int have_def_rec; char *answer = NULL; STRLIST backlog = NULL; if (pk_list) any_recipients = 1; def_rec = default_recipient(); have_def_rec = !!def_rec; if ( !have_def_rec ) tty_printf(_("You did not specify a user ID. (you may use \"-r\")\n")); for (;;) { rc = 0; xfree(answer); if ( have_def_rec ) { /* A default recipient is taken as the first entry. */ answer = def_rec; def_rec = NULL; } else if (backlog) { /* This is part of our trick to expand and display groups. */ answer = pop_strlist (&backlog); } else { /* Show the list of already collected recipients and ask for more. */ PK_LIST iter; tty_printf("\n"); tty_printf(_("Current recipients:\n")); for (iter=pk_list;iter;iter=iter->next) { u32 keyid[2]; keyid_from_pk(iter->pk,keyid); tty_printf("%4u%c/%s %s \"", nbits_from_pk(iter->pk), pubkey_letter(iter->pk->pubkey_algo), keystr(keyid), datestr_from_pk(iter->pk)); if (iter->pk->user_id) tty_print_utf8_string(iter->pk->user_id->name, iter->pk->user_id->len); else { size_t n; char *p = get_user_id( keyid, &n ); tty_print_utf8_string( p, n ); xfree(p); } tty_printf("\"\n"); } answer = cpr_get_utf8("pklist.user_id.enter", _("\nEnter the user ID. " "End with an empty line: ")); trim_spaces(answer); cpr_kill_prompt(); } if ( !answer || !*answer ) { xfree(answer); break; /* No more recipients entered - get out of loop. */ } /* Do group expand here too. The trick here is to continue the loop if any expansion occured. The code above will then list all expanded keys. */ if (expand_id(answer,&backlog,0)) continue; /* Get and check key for the current name. */ if (pk) free_public_key (pk); pk = xmalloc_clear( sizeof *pk ); pk->req_usage = use; rc = get_pubkey_byname( pk, answer, NULL, NULL, 0 ); if (rc) tty_printf(_("No such user ID.\n")); else if ( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) { if ( have_def_rec ) { /* No validation for a default recipient. */ if (!key_present_in_pk_list(pk_list, pk)) { free_public_key (pk); pk = NULL; log_info (_("skipped: public key " "already set as default recipient\n") ); } else { PK_LIST r = xmalloc (sizeof *r); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = 0; /* No throwing default ids. */ pk_list = r; } any_recipients = 1; continue; } else { /* Check validity of this key. */ int trustlevel; trustlevel = get_validity (pk, pk->user_id); if ( (trustlevel & TRUST_FLAG_DISABLED) ) { tty_printf (_("Public key is disabled.\n") ); } else if ( do_we_trust_pre (pk, trustlevel) ) { /* Skip the actual key if the key is already * present in the list */ if (!key_present_in_pk_list(pk_list, pk)) { free_public_key(pk); pk = NULL; log_info(_("skipped: public key already set\n") ); } else { PK_LIST r; r = xmalloc( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = 0; /* No throwing interactive ids. */ pk_list = r; } any_recipients = 1; continue; } } } xfree(def_rec); def_rec = NULL; have_def_rec = 0; } if ( pk ) { free_public_key( pk ); pk = NULL; } } else if ( !any_recipients && (def_rec = default_recipient()) ) { /* We are in batch mode and have only a default recipient. */ pk = xmalloc_clear( sizeof *pk ); pk->req_usage = use; /* The default recipient is allowed to be disabled; thus pass 1 as last argument. */ rc = get_pubkey_byname (pk, def_rec, NULL, NULL, 1); if (rc) log_error(_("unknown default recipient \"%s\"\n"), def_rec ); else if ( !(rc=check_pubkey_algo2(pk->pubkey_algo, use)) ) { /* Mark any_recipients here since the default recipient would have been used if it wasn't already there. It doesn't really matter if we got this key from the default recipient or an encrypt-to. */ any_recipients = 1; if (!key_present_in_pk_list(pk_list, pk)) log_info (_("skipped: public key already set " "as default recipient\n")); else { PK_LIST r = xmalloc( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = 0; /* No throwing default ids. */ pk_list = r; } } if ( pk ) { free_public_key( pk ); pk = NULL; } xfree(def_rec); def_rec = NULL; } else { /* General case: Check all keys. */ any_recipients = 0; for (; remusr; remusr = remusr->next ) { if ( (remusr->flags & 1) ) continue; /* encrypt-to keys are already handled. */ pk = xmalloc_clear( sizeof *pk ); pk->req_usage = use; if ( (rc = get_pubkey_byname( pk, remusr->d, NULL, NULL, 0 )) ) { /* Key not found or other error. */ free_public_key( pk ); pk = NULL; log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) ); write_status_text_and_buffer (STATUS_INV_RECP, "0 ", remusr->d, strlen (remusr->d), -1); goto fail; } else if ( !(rc=check_pubkey_algo2(pk->pubkey_algo, use )) ) { /* Key found and usable. Check validity. */ int trustlevel; trustlevel = get_validity (pk, pk->user_id); if ( (trustlevel & TRUST_FLAG_DISABLED) ) { /*Key has been disabled. */ free_public_key(pk); pk = NULL; log_info(_("%s: skipped: public key is disabled\n"), remusr->d); write_status_text_and_buffer (STATUS_INV_RECP, "0 ", remusr->d, strlen (remusr->d), -1); rc=G10ERR_UNU_PUBKEY; goto fail; } else if ( do_we_trust_pre( pk, trustlevel ) ) { /* Note: do_we_trust may have changed the trustlevel */ /* We have at least one valid recipient. It doesn't * matters if this recipient is already present. */ any_recipients = 1; /* Skip the actual key if the key is already present * in the list */ if (!key_present_in_pk_list(pk_list, pk)) { free_public_key(pk); pk = NULL; log_info(_("%s: skipped: public key already present\n"), remusr->d); } else { PK_LIST r; r = xmalloc( sizeof *r ); r->pk = pk; pk = NULL; r->next = pk_list; r->flags = (remusr->flags&2)?1:0; pk_list = r; } } else { /* We don't trust this key. */ free_public_key( pk ); pk = NULL; write_status_text_and_buffer (STATUS_INV_RECP, "10 ", remusr->d, strlen (remusr->d), -1); rc=G10ERR_UNU_PUBKEY; goto fail; } } else { /* Key found but not usable for us (e.g. sign-only key). */ free_public_key( pk ); pk = NULL; write_status_text_and_buffer (STATUS_INV_RECP, "0 ", remusr->d, strlen (remusr->d), -1); log_error(_("%s: skipped: %s\n"), remusr->d, g10_errstr(rc) ); goto fail; } } } if ( !rc && !any_recipients ) { log_error(_("no valid addressees\n")); write_status_text (STATUS_NO_RECP, "0"); rc = G10ERR_NO_USER_ID; } fail: if ( rc ) release_pk_list( pk_list ); else *ret_pk_list = pk_list; if (opt.grouplist) free_strlist(remusr); return rc; }
static int do_listkeys (assuan_context_t ctx, char *line, int mode) { ctrl_t ctrl = assuan_get_pointer (ctx); estream_t fp; char *p; strlist_t list, sl; unsigned int listmode; gpg_error_t err; /* Break the line down into an strlist. */ list = NULL; for (p=line; *p; line = p) { while (*p && *p != ' ') p++; if (*p) *p++ = 0; if (*line) { sl = xtrymalloc (sizeof *sl + strlen (line)); if (!sl) { free_strlist (list); return out_of_core (); } sl->flags = 0; strcpy_escaped_plus (sl->d, line); sl->next = list; list = sl; } } if (ctrl->server_local->list_to_output) { int outfd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1); if ( outfd == -1 ) return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL); fp = es_fdopen_nc (outfd, "w"); if (!fp) return set_error (gpg_err_code_from_syserror (), "es_fdopen() failed"); } else { fp = es_fopencookie (ctx, "w", data_line_cookie_functions); if (!fp) return set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream"); } ctrl->with_colons = 1; listmode = mode; if (ctrl->server_local->list_internal) listmode |= (1<<6); if (ctrl->server_local->list_external) listmode |= (1<<7); err = gpgsm_list_keys (assuan_get_pointer (ctx), list, fp, listmode); free_strlist (list); es_fclose (fp); if (ctrl->server_local->list_to_output) assuan_close_output_fd (ctx); return err; }
static gpg_error_t cmd_export (assuan_context_t ctx, char *line) { ctrl_t ctrl = assuan_get_pointer (ctx); char *p; strlist_t list, sl; int use_data; use_data = has_option (line, "--data"); if (use_data) { /* We need to override any possible setting done by an OUTPUT command. */ ctrl->create_pem = has_option (line, "--armor"); ctrl->create_base64 = has_option (line, "--base64"); } line = skip_options (line); /* Break the line down into an strlist_t. */ list = NULL; for (p=line; *p; line = p) { while (*p && *p != ' ') p++; if (*p) *p++ = 0; if (*line) { sl = xtrymalloc (sizeof *sl + strlen (line)); if (!sl) { free_strlist (list); return out_of_core (); } sl->flags = 0; strcpy_escaped_plus (sl->d, line); sl->next = list; list = sl; } } if (use_data) { estream_t stream; stream = es_fopencookie (ctx, "w", data_line_cookie_functions); if (!stream) { free_strlist (list); return set_error (GPG_ERR_ASS_GENERAL, "error setting up a data stream"); } gpgsm_export (ctrl, list, stream); es_fclose (stream); } else { int fd = translate_sys2libc_fd (assuan_get_output_fd (ctx), 1); estream_t out_fp; if (fd == -1) { free_strlist (list); return set_error (GPG_ERR_ASS_NO_OUTPUT, NULL); } out_fp = es_fdopen_nc (fd, "w"); if (!out_fp) { free_strlist (list); return set_error (gpg_err_code_from_syserror (), "fdopen() failed"); } gpgsm_export (ctrl, list, out_fp); es_fclose (out_fp); } free_strlist (list); /* Close and reset the fds. */ close_message_fd (ctrl); assuan_close_input_fd (ctx); assuan_close_output_fd (ctx); return 0; }
/* Import a key by name using LDAP */ int keyserver_import_ldap (ctrl_t ctrl, const char *name,unsigned char **fpr,size_t *fpr_len) { char *domain; struct keyserver_spec *keyserver; strlist_t list=NULL; int rc,hostlen=1; #ifdef USE_DNS_SRV struct srventry *srvlist=NULL; int srvcount,i; char srvname[MAXDNAME]; #endif /* Parse out the domain */ domain=strrchr(name,'@'); if(!domain) return G10ERR_GENERAL; domain++; keyserver=xmalloc_clear(sizeof(struct keyserver_spec)); keyserver->scheme=xstrdup("ldap"); keyserver->host=xmalloc(1); keyserver->host[0]='\0'; #ifdef USE_DNS_SRV snprintf(srvname,MAXDNAME,"_pgpkey-ldap._tcp.%s",domain); srvcount=getsrv(srvname,&srvlist); for(i=0;i<srvcount;i++) { hostlen+=strlen(srvlist[i].target)+1; keyserver->host=xrealloc(keyserver->host,hostlen); strcat(keyserver->host,srvlist[i].target); if(srvlist[i].port!=389) { char port[7]; hostlen+=6; /* a colon, plus 5 digits (unsigned 16-bit value) */ keyserver->host=xrealloc(keyserver->host,hostlen); snprintf(port,7,":%u",srvlist[i].port); strcat(keyserver->host,port); } strcat(keyserver->host," "); } free(srvlist); #endif /* If all else fails, do the PGP Universal trick of ldap://keys.(domain) */ hostlen+=5+strlen(domain); keyserver->host=xrealloc(keyserver->host,hostlen); strcat(keyserver->host,"keys."); strcat(keyserver->host,domain); append_to_strlist(&list,name); rc = gpg_error (GPG_ERR_NOT_IMPLEMENTED); /*FIXME*/ /* keyserver_work (ctrl, KS_GETNAME, list, NULL, */ /* 0, fpr, fpr_len, keyserver); */ free_strlist(list); free_keyserver_spec(keyserver); return rc; }
/* Prepare an LDAP query to return certificates matching PATTERNS using the SERVER. This function returns an error code or 0 and a CONTEXT on success. */ gpg_error_t start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context, strlist_t patterns, const ldap_server_t server) { gpg_error_t err; char *proxy = NULL; char *host = NULL; int port; char *user = NULL; char *pass = NULL; const char *base; char *argv[50]; int argc = 0; int argc_malloced = 0; char portbuf[30], timeoutbuf[30]; *context = NULL; if (opt.ldap_proxy && !(proxy = xtrystrdup (opt.ldap_proxy))) { err = gpg_error_from_syserror (); goto leave; } if (server) { if (server->host && !(host = xtrystrdup (server->host))) { err = gpg_error_from_syserror (); goto leave; } port = server->port; if (server->user && !(user = xtrystrdup (server->user))) { err = gpg_error_from_syserror (); goto leave; } if (server->pass && !(pass = xtrystrdup (server->pass))) { err = gpg_error_from_syserror (); goto leave; } base = server->base; } else /* Use a default server. */ return gpg_error (GPG_ERR_NOT_IMPLEMENTED); if (!base) base = ""; if (pass) /* Note: Must be the first item. */ { argv[argc++] = "--pass"; argv[argc++] = pass; } if (DBG_LOOKUP) argv[argc++] = "-vv"; else if (DBG_EXTPROG) argv[argc++] = "-v"; argv[argc++] = "--log-with-pid"; argv[argc++] = "--multi"; if (opt.ldaptimeout) { snprintf (timeoutbuf, sizeof timeoutbuf, "%u", opt.ldaptimeout); argv[argc++] = "--timeout"; argv[argc++] = timeoutbuf; } if (opt.ldap_proxy) { argv[argc++] = "--proxy"; argv[argc++] = proxy; } if (host) { argv[argc++] = "--host"; argv[argc++] = host; } if (port) { snprintf (portbuf, sizeof portbuf, "%d", port); argv[argc++] = "--port"; argv[argc++] = portbuf; } if (user) { argv[argc++] = "--user"; argv[argc++] = user; } /* All entries in argv from this index on are malloc'ed. */ argc_malloced = argc; for (; patterns; patterns = patterns->next) { strlist_t sl; char *url; if (argc >= DIM (argv) - 1) { /* Too many patterns. It does not make sense to allow an arbitrary number of patters because the length of the command line is limited anyway. */ /* fixme: cleanup. */ return gpg_error (GPG_ERR_RESOURCE_LIMIT); } sl = parse_one_pattern (patterns->d); if (!sl) { log_error (_("start_cert_fetch: invalid pattern '%s'\n"), patterns->d); err = gpg_error (GPG_ERR_INV_USER_ID); goto leave; } if ((sl->flags & 1)) err = make_url (&url, sl->d, "objectClass=*"); else err = make_url (&url, base, sl->d); free_strlist (sl); if (err) goto leave; argv[argc++] = url; } argv[argc] = NULL; *context = xtrycalloc (1, sizeof **context); if (!*context) { err = gpg_error_from_errno (errno); goto leave; } err = ldap_wrapper (ctrl, &(*context)->reader, (const char**)argv); if (err) { xfree (*context); *context = NULL; } leave: for (; argc_malloced < argc; argc_malloced++) xfree (argv[argc_malloced]); xfree (proxy); xfree (host); xfree (user); xfree (pass); return err; }