SENDSTREAM *smtp_open_full (NETDRIVER *dv,char **hostlist,char *service, unsigned long port,long options) { SENDSTREAM *stream = NIL; long reply; char *s,tmp[MAILTMPLEN]; NETSTREAM *netstream; NETMBX mb; if (!(hostlist && *hostlist)) mm_log ("Missing SMTP service host",ERROR); /* maximum domain name is 64 characters */ else do if (strlen (*hostlist) < SMTPMAXDOMAIN) { sprintf (tmp,"{%.1000s}",*hostlist); if (!mail_valid_net_parse_work (tmp,&mb,service ? service : "smtp") || mb.anoflag || mb.readonlyflag) { sprintf (tmp,"Invalid host specifier: %.80s",*hostlist); mm_log (tmp,ERROR); } else { /* light tryssl flag if requested */ mb.trysslflag = (options & SOP_TRYSSL) ? T : NIL; /* explicit port overrides all */ if (mb.port) port = mb.port; /* else /submit overrides port argument */ else if (!compare_cstring (mb.service,"submit")) { port = SUBMITTCPPORT; /* override port, use IANA name */ strcpy (mb.service,"submission"); } /* else port argument overrides SMTP port */ else if (!port) port = smtp_port ? smtp_port : SMTPTCPPORT; if (netstream = /* try to open ordinary connection */ net_open (&mb,dv,port, (NETDRIVER *) mail_parameters (NIL,GET_SSLDRIVER,NIL), "*smtps",smtp_sslport ? smtp_sslport : SMTPSSLPORT)) { stream = (SENDSTREAM *) memset (fs_get (sizeof (SENDSTREAM)),0, sizeof (SENDSTREAM)); stream->netstream = netstream; stream->host = cpystr ((long) mail_parameters (NIL,GET_TRUSTDNS,NIL) ? net_host (netstream) : mb.host); stream->debug = (mb.dbgflag || (options & OP_DEBUG)) ? T : NIL; if (options & SOP_SECURE) mb.secflag = T; /* get name of local host to use */ s = compare_cstring ("localhost",mb.host) ? net_localhost (netstream) : "localhost"; do reply = smtp_reply (stream); while ((reply < 100) || (stream->reply[3] == '-')); if (reply != SMTPGREET){/* get SMTP greeting */ sprintf (tmp,"SMTP greeting failure: %.80s",stream->reply); mm_log (tmp,ERROR); stream = smtp_close (stream); } /* try EHLO first, then HELO */ else if (((reply = smtp_ehlo (stream,s,&mb)) != SMTPOK) && ((reply = smtp_send (stream,"HELO",s)) != SMTPOK)) { sprintf (tmp,"SMTP hello failure: %.80s",stream->reply); mm_log (tmp,ERROR); stream = smtp_close (stream); } else { NETDRIVER *ssld =(NETDRIVER *)mail_parameters(NIL,GET_SSLDRIVER,NIL); sslstart_t stls = (sslstart_t) mail_parameters(NIL,GET_SSLSTART,NIL); ESMTP.ok = T; /* ESMTP server, start TLS if present */ if (!dv && stls && ESMTP.service.starttls && !mb.sslflag && !mb.notlsflag && (smtp_send (stream,"STARTTLS",NIL) == SMTPGREET)) { mb.tlsflag = T; /* TLS OK, get into TLS at this end */ stream->netstream->dtb = ssld; /* TLS started, negotiate it */ if (!(stream->netstream->stream = (*stls) (stream->netstream->stream,mb.host, (mb.tlssslv23 ? NIL : NET_TLSCLIENT) | (mb.novalidate ? NET_NOVALIDATECERT:NIL)))){ /* TLS negotiation failed after STARTTLS */ sprintf (tmp,"Unable to negotiate TLS with this server: %.80s", mb.host); mm_log (tmp,ERROR); /* close without doing QUIT */ if (stream->netstream) net_close (stream->netstream); stream->netstream = NIL; stream = smtp_close (stream); } /* TLS OK, re-negotiate EHLO */ else if ((reply = smtp_ehlo (stream,s,&mb)) != SMTPOK) { sprintf (tmp,"SMTP EHLO failure after STARTTLS: %.80s", stream->reply); mm_log (tmp,ERROR); stream = smtp_close (stream); } else ESMTP.ok = T; /* TLS OK and EHLO successful */ } else if (mb.tlsflag) {/* user specified /tls but can't do it */ sprintf (tmp,"TLS unavailable with this server: %.80s",mb.host); mm_log (tmp,ERROR); stream = smtp_close (stream); } /* remote name for authentication */ if (stream && ((mb.secflag || mb.user[0]))) { if (ESMTP.auth) { /* use authenticator? */ if ((long) mail_parameters (NIL,GET_TRUSTDNS,NIL)) { /* remote name for authentication */ strncpy (mb.host, (long) mail_parameters (NIL,GET_SASLUSESPTRNAME,NIL) ? net_remotehost (netstream) : net_host (netstream), NETMAXHOST-1); mb.host[NETMAXHOST-1] = '\0'; } if (!smtp_auth (stream,&mb,tmp)) stream = smtp_close (stream); } else { /* no available authenticators? */ sprintf (tmp,"%sSMTP authentication not available: %.80s", mb.secflag ? "Secure " : "",mb.host); mm_log (tmp,ERROR); stream = smtp_close (stream); } } } } } } while (!stream && *++hostlist); if (stream) { /* set stream options if have a stream */ if (options &(SOP_DSN | SOP_DSN_NOTIFY_FAILURE | SOP_DSN_NOTIFY_DELAY | SOP_DSN_NOTIFY_SUCCESS | SOP_DSN_RETURN_FULL)) { ESMTP.dsn.want = T; if (options & SOP_DSN_NOTIFY_FAILURE) ESMTP.dsn.notify.failure = T; if (options & SOP_DSN_NOTIFY_DELAY) ESMTP.dsn.notify.delay = T; if (options & SOP_DSN_NOTIFY_SUCCESS) ESMTP.dsn.notify.success = T; if (options & SOP_DSN_RETURN_FULL) ESMTP.dsn.full = T; } if (options & SOP_8BITMIME) ESMTP.eightbit.want = T; } return stream; }
/* * Do an LDAP lookup to the server described in the info argument. * * Args info -- LDAP info for server. * string -- String to lookup. * cust -- Possible custom filter description. * wp_err -- We set this is we get a white pages error. * name_in_error -- Caller sets this if they want us to include the server * name in error messages. * * Returns Results of lookup, NULL if lookup failed. */ LDAP_SERV_RES_S * ldap_lookup(LDAP_SERV_S *info, char *string, CUSTOM_FILT_S *cust, WP_ERR_S *wp_err, int name_in_error) { char ebuf[900]; char buf[900]; char *serv, *base, *serv_errstr; char *mailattr, *snattr, *gnattr, *cnattr; int we_cancel = 0, we_turned_on = 0; LDAP_SERV_RES_S *serv_res = NULL; LDAP *ld; long pwdtrial = 0L; int ld_errnum; char *ld_errstr; if(!info) return(serv_res); serv = cpystr((info->serv && *info->serv) ? info->serv : "?"); if(name_in_error) snprintf(ebuf, sizeof(ebuf), " (%s)", (info->nick && *info->nick) ? info->nick : serv); else ebuf[0] = '\0'; serv_errstr = cpystr(ebuf); base = cpystr(info->base ? info->base : ""); if(info->port < 0) info->port = LDAP_PORT; if(info->type < 0) info->type = DEF_LDAP_TYPE; if(info->srch < 0) info->srch = DEF_LDAP_SRCH; if(info->time < 0) info->time = DEF_LDAP_TIME; if(info->size < 0) info->size = DEF_LDAP_SIZE; if(info->scope < 0) info->scope = DEF_LDAP_SCOPE; mailattr = (info->mailattr && info->mailattr[0]) ? info->mailattr : DEF_LDAP_MAILATTR; snattr = (info->snattr && info->snattr[0]) ? info->snattr : DEF_LDAP_SNATTR; gnattr = (info->gnattr && info->gnattr[0]) ? info->gnattr : DEF_LDAP_GNATTR; cnattr = (info->cnattr && info->cnattr[0]) ? info->cnattr : DEF_LDAP_CNATTR; /* * We may want to keep ldap handles open, but at least for * now, re-open them every time. */ dprint((3, "ldap_lookup(%s,%d)\n", serv ? serv : "?", info->port)); snprintf(ebuf, sizeof(ebuf), "Searching%s%s%s on %s", (string && *string) ? " for \"" : "", (string && *string) ? string : "", (string && *string) ? "\"" : "", serv); we_turned_on = intr_handling_on(); /* this erases keymenu */ we_cancel = busy_cue(ebuf, NULL, 0); if(wp_err->mangled) *(wp_err->mangled) = 1; #ifdef _SOLARIS_SDK if(info->tls || info->tlsmust) ldapssl_client_init(NULL, NULL); if((ld = ldap_init(serv, info->port)) == NULL) #else #if (LDAPAPI >= 11) if((ld = ldap_init(serv, info->port)) == NULL) #else if((ld = ldap_open(serv, info->port)) == NULL) #endif #endif { /* TRANSLATORS: All of the three args together are an error message */ snprintf(ebuf, sizeof(ebuf), _("Access to LDAP server failed: %s%s(%s)"), errno ? error_description(errno) : "", errno ? " " : "", serv); wp_err->wp_err_occurred = 1; if(wp_err->error) fs_give((void **)&wp_err->error); wp_err->error = cpystr(ebuf); if(we_cancel) cancel_busy_cue(-1); q_status_message(SM_ORDER, 3, 5, wp_err->error); display_message('x'); dprint((2, "%s\n", ebuf)); } else if(!ps_global->intr_pending){ int proto = 3, tlsmustbail = 0; char pwd[NETMAXPASSWD], user[NETMAXUSER]; char *passwd = NULL; char hostbuf[1024]; NETMBX mb; #ifndef _WINDOWS int rc; #endif memset(&mb, 0, sizeof(mb)); #ifdef _SOLARIS_SDK if(info->tls || info->tlsmust) rc = ldapssl_install_routines(ld); #endif if(ldap_v3_is_supported(ld) && our_ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &proto) == 0){ dprint((5, "ldap: using version 3 protocol\n")); } /* * If we don't set RESTART then the select() waiting for the answer * in libldap will be interrupted and stopped by our busy_cue. */ our_ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON); /* * If we need to authenticate, get the password. We are not * supporting SASL authentication, just LDAP simple. */ if(info->binddn && info->binddn[0]){ char pmt[500]; char *space; snprintf(hostbuf, sizeof(hostbuf), "{%s}dummy", info->serv ? info->serv : "?"); /* * We don't handle multiple space-delimited hosts well. * We don't know which we're asking for a password for. * We're not connected yet so we can't know. */ if((space=strindex(hostbuf, ' ')) != NULL) *space = '\0'; mail_valid_net_parse_work(hostbuf, &mb, "ldap"); mb.port = info->port; mb.tlsflag = (info->tls || info->tlsmust) ? 1 : 0; try_password_again: if(mb.tlsflag && (pwdtrial > 0 || #ifndef _WINDOWS #ifdef _SOLARIS_SDK (rc == LDAP_SUCCESS) #else /* !_SOLARIS_SDK */ ((rc=ldap_start_tls_s(ld, NULL, NULL)) == LDAP_SUCCESS) #endif /* !_SOLARIS_SDK */ #else /* _WINDOWS */ 0 /* TODO: find a way to do this in Windows */ #endif /* _WINDOWS */ )) mb.tlsflag = 1; else mb.tlsflag = 0; if((info->tls || info->tlsmust) && !mb.tlsflag){ q_status_message(SM_ORDER, 3, 5, "Not able to start TLS encryption for LDAP server"); if(info->tlsmust) tlsmustbail++; } if(!tlsmustbail){ snprintf(pmt, sizeof(pmt), " %s", (info->nick && *info->nick) ? info->nick : serv); mm_login_work(&mb, user, pwd, pwdtrial, pmt, info->binddn); if(pwd && pwd[0]) passwd = pwd; } } /* * LDAPv2 requires the bind. v3 doesn't require it but we want * to tell the server we're v3 if the server supports v3, and if the * server doesn't support v3 the bind is required. */ if(tlsmustbail || ldap_simple_bind_s(ld, info->binddn, passwd) != LDAP_SUCCESS){ wp_err->wp_err_occurred = 1; ld_errnum = our_ldap_get_lderrno(ld, NULL, &ld_errstr); if(!tlsmustbail && info->binddn && info->binddn[0] && pwdtrial < 2L && ld_errnum == LDAP_INVALID_CREDENTIALS){ pwdtrial++; q_status_message(SM_ORDER, 3, 5, _("Invalid password")); goto try_password_again; } snprintf(ebuf, sizeof(ebuf), _("LDAP server failed: %s%s%s%s"), ldap_err2string(ld_errnum), serv_errstr, (ld_errstr && *ld_errstr) ? ": " : "", (ld_errstr && *ld_errstr) ? ld_errstr : ""); if(wp_err->error) fs_give((void **)&wp_err->error); if(we_cancel) cancel_busy_cue(-1); ldap_unbind(ld); wp_err->error = cpystr(ebuf); q_status_message(SM_ORDER, 3, 5, wp_err->error); display_message('x'); dprint((2, "%s\n", ebuf)); } else if(!ps_global->intr_pending){ int srch_res, args, slen, flen; #define TEMPLATELEN 512 char filt_template[TEMPLATELEN + 1]; char filt_format[2*TEMPLATELEN + 1]; char filter[2*TEMPLATELEN + 1]; char scp[2*TEMPLATELEN + 1]; char *p, *q; LDAPMessage *res = NULL; int intr_happened = 0; int tl; tl = (info->time == 0) ? info->time : info->time + 10; our_ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &tl); our_ldap_set_option(ld, LDAP_OPT_SIZELIMIT, &info->size); /* * If a custom filter has been passed in and it doesn't include a * request to combine it with the configured filter, then replace * any configured filter with the passed in filter. */ if(cust && cust->filt && !cust->combine){ if(info->cust) fs_give((void **)&info->cust); info->cust = cpystr(cust->filt); } if(info->cust && *info->cust){ /* use custom filter if present */ strncpy(filt_template, info->cust, sizeof(filt_template)); filt_template[sizeof(filt_template)-1] = '\0'; } else{ /* else use configured filter */ switch(info->type){ case LDAP_TYPE_SUR: snprintf(filt_template, sizeof(filt_template), "(%s=%%s)", snattr); break; case LDAP_TYPE_GIVEN: snprintf(filt_template, sizeof(filt_template), "(%s=%%s)", gnattr); break; case LDAP_TYPE_EMAIL: snprintf(filt_template, sizeof(filt_template), "(%s=%%s)", mailattr); break; case LDAP_TYPE_CN_EMAIL: snprintf(filt_template, sizeof(filt_template), "(|(%s=%%s)(%s=%%s))", cnattr, mailattr); break; case LDAP_TYPE_SUR_GIVEN: snprintf(filt_template, sizeof(filt_template), "(|(%s=%%s)(%s=%%s))", snattr, gnattr); break; case LDAP_TYPE_SEVERAL: snprintf(filt_template, sizeof(filt_template), "(|(%s=%%s)(%s=%%s)(%s=%%s)(%s=%%s))", cnattr, mailattr, snattr, gnattr); break; default: case LDAP_TYPE_CN: snprintf(filt_template, sizeof(filt_template), "(%s=%%s)", cnattr); break; } } /* just copy if custom */ if(info->cust && *info->cust) info->srch = LDAP_SRCH_EQUALS; p = filt_template; q = filt_format; memset((void *)filt_format, 0, sizeof(filt_format)); args = 0; while(*p && (q - filt_format) + 4 < sizeof(filt_format)){ if(*p == '%' && *(p+1) == 's'){ args++; switch(info->srch){ /* Exact match */ case LDAP_SRCH_EQUALS: *q++ = *p++; *q++ = *p++; break; /* Append wildcard after %s */ case LDAP_SRCH_BEGINS: *q++ = *p++; *q++ = *p++; *q++ = '*'; break; /* Insert wildcard before %s */ case LDAP_SRCH_ENDS: *q++ = '*'; *q++ = *p++; *q++ = *p++; break; /* Put wildcard before and after %s */ default: case LDAP_SRCH_CONTAINS: *q++ = '*'; *q++ = *p++; *q++ = *p++; *q++ = '*'; break; } } else *q++ = *p++; } if(q - filt_format < sizeof(filt_format)) *q = '\0'; filt_format[sizeof(filt_format)-1] = '\0'; /* * If combine is lit we put the custom filter and the filt_format * filter and combine them with an &. */ if(cust && cust->filt && cust->combine){ char *combined; size_t l; l = strlen(filt_format) + strlen(cust->filt) + 3; combined = (char *) fs_get((l+1) * sizeof(char)); snprintf(combined, l+1, "(&%s%s)", cust->filt, filt_format); strncpy(filt_format, combined, sizeof(filt_format)); filt_format[sizeof(filt_format)-1] = '\0'; fs_give((void **) &combined); } /* * Ad hoc attempt to make "Steve Hubert" match * Steven Hubert but not Steven Shubert. * We replace a <SPACE> with * <SPACE> (not * <SPACE> *). */ memset((void *)scp, 0, sizeof(scp)); if(info->nosub) strncpy(scp, string, sizeof(scp)); else{ p = string; q = scp; while(*p && (q - scp) + 1 < sizeof(scp)){ if(*p == SPACE && *(p+1) != SPACE){ *q++ = '*'; *q++ = *p++; } else *q++ = *p++; } } scp[sizeof(scp)-1] = '\0'; slen = strlen(scp); flen = strlen(filt_format); /* truncate string if it will overflow filter */ if(args*slen + flen - 2*args > sizeof(filter)-1) scp[(sizeof(filter)-1 - flen)/args] = '\0'; /* * Replace %s's with scp. */ switch(args){ case 0: snprintf(filter, sizeof(filter), "%s", filt_format); break; case 1: snprintf(filter, sizeof(filter), filt_format, scp); break; case 2: snprintf(filter, sizeof(filter), filt_format, scp, scp); break; case 3: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp); break; case 4: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp); break; case 5: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp, scp); break; case 6: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp, scp, scp); break; case 7: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp, scp, scp, scp); break; case 8: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp, scp, scp, scp, scp); break; case 9: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp, scp, scp, scp, scp, scp); break; case 10: default: snprintf(filter, sizeof(filter), filt_format, scp, scp, scp, scp, scp, scp, scp, scp, scp, scp); break; } /* replace double *'s with single *'s in filter */ for(p = q = filter; *p; p++) if(*p != '*' || p == filter || *(p-1) != '*') *q++ = *p; *q = '\0'; (void) removing_double_quotes(base); dprint((5, "about to ldap_search(\"%s\", %s)\n", base ? base : "?", filter ? filter : "?")); if(ps_global->intr_pending) srch_res = LDAP_PROTOCOL_ERROR; else{ int msgid; time_t start_time; start_time = time((time_t *)0); dprint((6, "ldap_lookup: calling ldap_search\n")); msgid = ldap_search(ld, base, info->scope, filter, NULL, 0); if(msgid == -1) srch_res = our_ldap_get_lderrno(ld, NULL, NULL); else{ int lres; /* * Warning: struct timeval is not portable. However, since it is * part of LDAP api it must be portable to all platforms LDAP * has been ported to. */ struct timeval t; t.tv_sec = 1; t.tv_usec = 0; do { if(ps_global->intr_pending) intr_happened = 1; dprint((6, "ldap_result(id=%d): ", msgid)); if((lres=ldap_result(ld, msgid, LDAP_MSG_ALL, &t, &res)) == -1){ /* error */ srch_res = our_ldap_get_lderrno(ld, NULL, NULL); dprint((6, "error (-1 returned): ld_errno=%d\n", srch_res)); } else if(lres == 0){ /* timeout, no results available */ if(intr_happened){ ldap_abandon(ld, msgid); srch_res = LDAP_PROTOCOL_ERROR; if(our_ldap_get_lderrno(ld, NULL, NULL) == LDAP_SUCCESS) our_ldap_set_lderrno(ld, LDAP_PROTOCOL_ERROR, NULL, NULL); dprint((6, "timeout, intr: srch_res=%d\n", srch_res)); } else if(info->time > 0 && ((long)time((time_t *)0) - start_time) > info->time){ /* try for partial results */ t.tv_sec = 0; t.tv_usec = 0; lres = ldap_result(ld, msgid, LDAP_MSG_RECEIVED, &t, &res); if(lres > 0 && lres != LDAP_RES_SEARCH_RESULT){ srch_res = LDAP_SUCCESS; dprint((6, "partial result: lres=0x%x\n", lres)); } else{ if(lres == 0) ldap_abandon(ld, msgid); srch_res = LDAP_TIMEOUT; if(our_ldap_get_lderrno(ld, NULL, NULL) == LDAP_SUCCESS) our_ldap_set_lderrno(ld, LDAP_TIMEOUT, NULL, NULL); dprint((6, "timeout, total_time (%d), srch_res=%d\n", info->time, srch_res)); } } else{ dprint((6, "timeout\n")); } } else{ srch_res = ldap_result2error(ld, res, 0); dprint((6, "lres=0x%x, srch_res=%d\n", lres, srch_res)); } }while(lres == 0 && !(intr_happened || (info->time > 0 && ((long)time((time_t *)0) - start_time) > info->time))); } } if(intr_happened){ wp_exit = 1; if(we_cancel) cancel_busy_cue(-1); if(wp_err->error) fs_give((void **)&wp_err->error); else{ q_status_message(SM_ORDER, 0, 1, "Interrupt"); display_message('x'); fflush(stdout); } if(res) ldap_msgfree(res); if(ld) ldap_unbind(ld); res = NULL; ld = NULL; } else if(srch_res != LDAP_SUCCESS && srch_res != LDAP_TIMELIMIT_EXCEEDED && srch_res != LDAP_RESULTS_TOO_LARGE && srch_res != LDAP_TIMEOUT && srch_res != LDAP_SIZELIMIT_EXCEEDED){ wp_err->wp_err_occurred = 1; ld_errnum = our_ldap_get_lderrno(ld, NULL, &ld_errstr); snprintf(ebuf, sizeof(ebuf), _("LDAP search failed: %s%s%s%s"), ldap_err2string(ld_errnum), serv_errstr, (ld_errstr && *ld_errstr) ? ": " : "", (ld_errstr && *ld_errstr) ? ld_errstr : ""); if(wp_err->error) fs_give((void **)&wp_err->error); wp_err->error = cpystr(ebuf); if(we_cancel) cancel_busy_cue(-1); q_status_message(SM_ORDER, 3, 5, wp_err->error); display_message('x'); dprint((2, "%s\n", ebuf)); if(res) ldap_msgfree(res); if(ld) ldap_unbind(ld); res = NULL; ld = NULL; } else{ int cnt; cnt = ldap_count_entries(ld, res); if(cnt > 0){ if(srch_res == LDAP_TIMELIMIT_EXCEEDED || srch_res == LDAP_RESULTS_TOO_LARGE || srch_res == LDAP_TIMEOUT || srch_res == LDAP_SIZELIMIT_EXCEEDED){ wp_err->wp_err_occurred = 1; ld_errnum = our_ldap_get_lderrno(ld, NULL, &ld_errstr); snprintf(ebuf, sizeof(ebuf), _("LDAP partial results: %s%s%s%s"), ldap_err2string(ld_errnum), serv_errstr, (ld_errstr && *ld_errstr) ? ": " : "", (ld_errstr && *ld_errstr) ? ld_errstr : ""); dprint((2, "%s\n", ebuf)); if(wp_err->error) fs_give((void **)&wp_err->error); wp_err->error = cpystr(ebuf); if(we_cancel) cancel_busy_cue(-1); q_status_message(SM_ORDER, 3, 5, wp_err->error); display_message('x'); } dprint((5, "Matched %d entries on %s\n", cnt, serv ? serv : "?")); serv_res = (LDAP_SERV_RES_S *)fs_get(sizeof(LDAP_SERV_RES_S)); memset((void *)serv_res, 0, sizeof(*serv_res)); serv_res->ld = ld; serv_res->res = res; serv_res->info_used = copy_ldap_serv_info(info); /* Save by reference? */ if(info->ref){ snprintf(buf, sizeof(buf), "%s:%s", serv, comatose(info->port)); serv_res->serv = cpystr(buf); } else serv_res->serv = NULL; serv_res->next = NULL; } else{ if(srch_res == LDAP_TIMELIMIT_EXCEEDED || srch_res == LDAP_RESULTS_TOO_LARGE || srch_res == LDAP_TIMEOUT || srch_res == LDAP_SIZELIMIT_EXCEEDED){ wp_err->wp_err_occurred = 1; wp_err->ldap_errno = srch_res; ld_errnum = our_ldap_get_lderrno(ld, NULL, &ld_errstr); snprintf(ebuf, sizeof(ebuf), _("LDAP search failed: %s%s%s%s"), ldap_err2string(ld_errnum), serv_errstr, (ld_errstr && *ld_errstr) ? ": " : "", (ld_errstr && *ld_errstr) ? ld_errstr : ""); if(wp_err->error) fs_give((void **)&wp_err->error); wp_err->error = cpystr(ebuf); if(we_cancel) cancel_busy_cue(-1); q_status_message(SM_ORDER, 3, 5, wp_err->error); display_message('x'); dprint((2, "%s\n", ebuf)); } dprint((5, "Matched 0 entries on %s\n", serv ? serv : "?")); if(res) ldap_msgfree(res); if(ld) ldap_unbind(ld); res = NULL; ld = NULL; } } } } if(we_cancel) cancel_busy_cue(-1); if(we_turned_on) intr_handling_off(); if(serv) fs_give((void **)&serv); if(base) fs_give((void **)&base); if(serv_errstr) fs_give((void **)&serv_errstr); return(serv_res); }