summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alpine/ldapconf.c99
-rw-r--r--pith/ldap.c66
-rw-r--r--pith/ldap.h1
-rw-r--r--pith/pine.hlp41
4 files changed, 200 insertions, 7 deletions
diff --git a/alpine/ldapconf.c b/alpine/ldapconf.c
index c051f625..36993de4 100644
--- a/alpine/ldapconf.c
+++ b/alpine/ldapconf.c
@@ -1146,6 +1146,7 @@ dir_config_edit(struct pine *ps, CONF_S **cl)
#define LDAP_F_NOSUB 3
#define LDAP_F_TLS 4
#define LDAP_F_TLSMUST 5
+#define LDAP_F_LDAPS 6
bitmap_t ldap_option_list;
struct variable *ldap_srch_rule_ptr;
@@ -1352,6 +1353,8 @@ dir_edit_screen(struct pine *ps, LDAP_SERV_S *def, char *title, char **raw_serve
setbitn(LDAP_F_TLS, ldap_option_list);
if(def && def->tlsmust)
setbitn(LDAP_F_TLSMUST, ldap_option_list);
+ if(def && def->ldaps)
+ setbitn(LDAP_F_LDAPS, ldap_option_list);
/* save the old opt_screen before calling scroll screen again */
saved_screen = opt_screen;
@@ -1475,6 +1478,38 @@ dir_edit_screen(struct pine *ps, LDAP_SERV_S *def, char *title, char **raw_serve
lv = MIN(lv, 100);
+ /* enabling ldaps disables tls */
+ if((f = ldap_feature_list(LDAP_F_LDAPS)) != NULL
+ && bitnset(f->value, ldap_option_list)){
+ int clear = 0;
+ if((f = ldap_feature_list(LDAP_F_TLS)) != NULL
+ && bitnset(f->value, ldap_option_list)){
+ clear++;
+ clrbitn(f->value, ldap_option_list);
+ }
+ if((f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL
+ && bitnset(f->value, ldap_option_list)){
+ clear++;
+ clrbitn(f->value, ldap_option_list);
+ }
+ if(clear > 0)
+ q_status_message(SM_ORDER, 3, 3,
+ _("Can not use TLS when connecting using LDAPS"));
+ }
+
+ /* enabling tls disables ldaps */
+ if(((f = ldap_feature_list(LDAP_F_TLS)) != NULL
+ && bitnset(f->value, ldap_option_list))
+ || ((f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL
+ && bitnset(f->value, ldap_option_list))){
+ if((f = ldap_feature_list(LDAP_F_LDAPS)) != NULL
+ && bitnset(f->value, ldap_option_list)){
+ clrbitn(f->value, ldap_option_list);
+ q_status_message(SM_ORDER, 3, 3,
+ _("Can not use LDAPS when connecting using TLS"));
+ }
+ }
+
for(i = 0; (f = ldap_feature_list(i)); i++){
new_confline(&ctmp);
ctmp->var = &opt_var;
@@ -1500,6 +1535,9 @@ dir_edit_screen(struct pine *ps, LDAP_SERV_S *def, char *title, char **raw_serve
case LDAP_F_TLSMUST:
ctmp->help = h_config_ldap_opts_tlsmust;
break;
+ case LDAP_F_LDAPS:
+ ctmp->help = h_config_ldap_opts_ldaps; //TODO: SSL and TLS as radiobutton
+ break;
}
ctmp->tool = ldap_checkbox_tool;
@@ -1920,7 +1958,7 @@ dir_edit_screen(struct pine *ps, LDAP_SERV_S *def, char *title, char **raw_serve
}
}
- snprintf(dir_tmp, sizeof(dir_tmp), "%s%s%s \"/base=%s/binddn=%s/impl=%d/rhs=%d/ref=%d/nosub=%d/tls=%d/tlsm=%d/type=%s/srch=%s%s/time=%s/size=%s/cust=%s/nick=%s/matr=%s/catr=%s/satr=%s/gatr=%s\"",
+ snprintf(dir_tmp, sizeof(dir_tmp), "%s%s%s \"/base=%s/binddn=%s/impl=%d/rhs=%d/ref=%d/nosub=%d/tls=%d/tlsm=%d/ldaps=%d/type=%s/srch=%s%s/time=%s/size=%s/cust=%s/nick=%s/matr=%s/catr=%s/satr=%s/gatr=%s\"",
server ? server : "",
(portval >= 0 && port && *port) ? ":" : "",
(portval >= 0 && port && *port) ? port : "",
@@ -1932,6 +1970,7 @@ dir_edit_screen(struct pine *ps, LDAP_SERV_S *def, char *title, char **raw_serve
bitnset(LDAP_F_NOSUB, ldap_option_list) ? 1 : 0,
bitnset(LDAP_F_TLS, ldap_option_list) ? 1 : 0,
bitnset(LDAP_F_TLSMUST, ldap_option_list) ? 1 : 0,
+ bitnset(LDAP_F_LDAPS, ldap_option_list) ? 1 : 0,
srch_type ? srch_type : "",
srch_rule ? srch_rule : "",
custom_scope,
@@ -2342,6 +2381,21 @@ void
toggle_ldap_option_bit(struct pine *ps, int index, struct variable *var, char *value)
{
NAMEVAL_S *f;
+ int tls_is_on_now;
+ int tlsmust_is_on_now;
+ int ldaps_is_on_now;
+ int tls_is_on_after;
+ int tlsmust_is_on_after;
+ int ldaps_is_on_after;
+
+ tls_is_on_now = (f = ldap_feature_list(LDAP_F_TLS)) != NULL
+ && bitnset(f->value, ldap_option_list) ? 1 : 0;
+
+ tlsmust_is_on_now = (f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL
+ && bitnset(f->value, ldap_option_list) ? 1 : 0;
+
+ ldaps_is_on_now = (f = ldap_feature_list(LDAP_F_LDAPS)) != NULL
+ && bitnset(f->value, ldap_option_list) ? 1 : 0;
f = ldap_feature_list(index);
@@ -2351,6 +2405,46 @@ toggle_ldap_option_bit(struct pine *ps, int index, struct variable *var, char *v
else
setbitn(f->value, ldap_option_list);
+ tls_is_on_after = (f = ldap_feature_list(LDAP_F_TLS)) != NULL
+ && bitnset(f->value, ldap_option_list) ? 1 : 0;
+
+ tlsmust_is_on_after = (f = ldap_feature_list(LDAP_F_TLSMUST)) != NULL
+ && bitnset(f->value, ldap_option_list) ? 1 : 0;
+
+ ldaps_is_on_after = (f = ldap_feature_list(LDAP_F_LDAPS)) != NULL
+ && bitnset(f->value, ldap_option_list) ? 1 : 0;
+
+ f = ldap_feature_list(index);
+
+ if(!ldaps_is_on_now && ldaps_is_on_after){
+ if(tlsmust_is_on_after || tls_is_on_after){
+ char *name;
+ if(tlsmust_is_on_after)
+ name = ldap_feature_list(LDAP_F_TLSMUST)->name;
+ else
+ name = ldap_feature_list(LDAP_F_TLS)->name;
+ clrbitn(f->value, ldap_option_list);
+ q_status_message1(SM_ORDER, 3, 3,
+ _("Can not use LDAPS when using TLS. Disable \"%s\" first."), name);
+ }
+ }
+ else if(!tls_is_on_now && tls_is_on_after){
+ if(ldaps_is_on_after){
+ char *name = ldap_feature_list(LDAP_F_LDAPS)->name;
+ clrbitn(f->value, ldap_option_list);
+ q_status_message1(SM_ORDER, 3, 3,
+ _("Can not use TLS when using LDAPS. Disable \"%s\" first."), name);
+ }
+ }
+ else if(!tlsmust_is_on_now && tlsmust_is_on_after){
+ if(ldaps_is_on_after){
+ char *name = ldap_feature_list(LDAP_F_LDAPS)->name;
+ clrbitn(f->value, ldap_option_list);
+ q_status_message1(SM_ORDER, 3, 3,
+ _("Can not use TLS when using LDAPS. Disable \"%s\" first."), name);
+ }
+ }
+
if(value)
value[1] = bitnset(f->value, ldap_option_list) ? 'X' : ' ';
}
@@ -2365,7 +2459,8 @@ ldap_feature_list(int index)
{"save-search-criteria-not-result", NULL, LDAP_F_REF},
{"disable-ad-hoc-space-substitution", NULL, LDAP_F_NOSUB},
{"attempt-tls-on-connection", NULL, LDAP_F_TLS},
- {"require-tls-on-connection", NULL, LDAP_F_TLSMUST}
+ {"require-tls-on-connection", NULL, LDAP_F_TLSMUST}, // TODO rename tls to starttls
+ {"require-ldaps-on-connection", NULL, LDAP_F_LDAPS}
};
return((index >= 0 &&
diff --git a/pith/ldap.c b/pith/ldap.c
index 78201de5..8bec9c06 100644
--- a/pith/ldap.c
+++ b/pith/ldap.c
@@ -26,7 +26,7 @@ static char rcsid[] = "$Id: ldap.c 1204 2009-02-02 19:54:23Z hubert@u.washington
#include "../pith/busy.h"
#include "../pith/signal.h"
#include "../pith/ablookup.h"
-
+#include "../pith/readfile.h"
/*
* Until we can think of a better way to do this. If user exits from an
@@ -475,7 +475,59 @@ ldap_lookup(LDAP_SERV_S *info, char *string, CUSTOM_FILT_S *cust,
#ifdef _WINDOWS
if((ld = ldap_init(serv, info->port)) == NULL)
#else
- snprintf(tmp_20k_buf, SIZEOF_20KBUF, "ldap://%s:%d", serv, info->port);
+#ifdef SMIME_SSLCERTS
+ /* If we are attempting a ldaps secure connection, we need to tell
+ * ldap that we have certificates. There are many ways to do so.
+ * OpenLDAP has many ways to configure this through configuration
+ * files. For example the global (to the system) ldap.conf file, or the
+ * personal ldaprc or .ldaprc files. Setting the location of the
+ * certificates must happen at the time we call ldap_initialize, we
+ * cannot set it up before that call, nor after, so what we are going
+ * to do is to test for a .ldaprc file in the home directory. If such
+ * file exists we read it, if not we create it and if it does not have
+ * a line for the location of the certificates in the system, we add one.
+ * (so we ignore all other configuration files)
+ */
+ if(info->ldaps && ps_global->home_dir){
+ int done = 0;
+ char *text, *tls_conf;
+ char filename[MAXPATH+1];
+
+ build_path(filename, ps_global->home_dir, ".ldaprc", sizeof(filename));
+
+ if((text = read_file(filename, 0)) != NULL)
+ while(done == 0
+ && (tls_conf = strstr(text, "TLS_CACERTDIR")) != NULL
+ && (tls_conf == text || *(tls_conf - 1) == '\n')){
+ tls_conf += 13; /* 13 = strlen("TLS_CACERTDIR") */
+ while (isspace(*tls_conf))
+ tls_conf++;
+ if(!strncmp(tls_conf, SMIME_SSLCERTS, strlen(SMIME_SSLCERTS)))
+ done++;
+ }
+
+ if(!done){
+ STORE_S *so;
+
+ if((so = so_get(FileStar, filename, WRITE_ACCESS)) != NULL){
+ if(text != NULL){
+ so_puts(so, text);
+ so_puts(so, NEWLINE);
+ }
+ so_puts(so, "TLS_CACERTDIR");
+ so_puts(so, " ");
+ so_puts(so, SMIME_SSLCERTS);
+ so_puts(so, NEWLINE);
+ so_give(&so);
+ }
+ }
+ if(text != NULL)
+ fs_give((void **)&text);
+ }
+#endif /* SMIME_SSLCERTS */
+
+ snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s://%s:%d",
+ info->ldaps ? "ldaps" : "ldap ", serv, info->port);
tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
if(ldap_initialize(&ld, tmp_20k_buf) != LDAP_SUCCESS)
@@ -535,8 +587,7 @@ ldap_lookup(LDAP_SERV_S *info, char *string, CUSTOM_FILT_S *cust,
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 we need to authenticate, get the password
*/
if(info->binddn && info->binddn[0]){
char pmt[500];
@@ -552,9 +603,10 @@ ldap_lookup(LDAP_SERV_S *info, char *string, CUSTOM_FILT_S *cust,
if((space=strindex(hostbuf, ' ')) != NULL)
*space = '\0';
- mail_valid_net_parse_work(hostbuf, &mb, "ldap");
+ mail_valid_net_parse_work(hostbuf, &mb, info->ldaps ? "ldaps" : "ldap");
mb.port = info->port;
mb.tlsflag = (info->tls || info->tlsmust) ? 1 : 0;
+ mb.sslflag = info->ldaps ? 1 : 0;
try_password_again:
@@ -1416,6 +1468,10 @@ break_up_ldap_server(char *serv_str)
if((q = srchstr(tail, "/tlsm=1")) != NULL)
info->tlsmust = 1;
+ /* get the ldaps parameter */
+ if((q = srchstr(tail, "/ldaps=1")) != NULL)
+ info->ldaps = 1;
+
/* get the search type value */
if((q = srchstr(tail, "/type=")) != NULL){
NAMEVAL_S *v;
diff --git a/pith/ldap.h b/pith/ldap.h
index b89a6511..b0cc30df 100644
--- a/pith/ldap.h
+++ b/pith/ldap.h
@@ -48,6 +48,7 @@ typedef struct ldap_serv {
nosub, /* Disable space sub feature */
tls, /* Attempt TLS */
tlsmust, /* Require TLS */
+ ldaps, /* Require LDAPS */
type, /* Search type (surname...) */
srch, /* Search rule (contains...) */
scope; /* Scope of search (base...) */
diff --git a/pith/pine.hlp b/pith/pine.hlp
index 21ca2553..f0b27fab 100644
--- a/pith/pine.hlp
+++ b/pith/pine.hlp
@@ -185,6 +185,9 @@ Additions include:
variable are "en_US" or "de_DE", etc. Only the first 10
dictionaries are offered.
+ <LI> Unix-Alpine: Connect securely to a LDAP server on a secure port.
+ Based on a contribution by Wang Kang.
+
<LI> Added support for RFC 2971 - IMAP ID extension.
<LI> Add configuration <A href="h_config_ignore_size"><!--#echo var="FEAT_ignore-size-changes"--></A>
@@ -3934,6 +3937,7 @@ There are also additional details on
<li><a href="h_config_ldap_opts_nosub">LDAP FEATURE: Disable-Ad-Hoc-Space-Substitution</a>
<li><a href="h_config_ldap_opts_rhs">LDAP FEATURE: Lookup-Addrbook-Contents</a>
<li><a href="h_config_ldap_opts_tlsmust">LDAP FEATURE: Require-TLS-On-Connection</a>
+<li><a href="h_config_ldap_opts_ldaps">LDAP FEATURE: Require-LDAPS-On-Connection</a>
<li><a href="h_config_ldap_opts_ref">LDAP FEATURE: Save-Search-Criteria-Not-Result</a>
<li><a href="h_config_ldap_opts_impl">LDAP FEATURE: Use-Implicitly-From-Composer</a>
<li><a href="h_config_ldap_binddn">LDAP OPTION: Bind-DN</a>
@@ -14882,6 +14886,14 @@ on the connection.
Also see the closely related feature
<A HREF="h_config_ldap_opts_tlsmust">&quot;Require-TLS-On-Connection&quot;</A>
<P>
+Note that if this option is set, then
+<A HREF="h_config_ldap_opts_ldaps">
+&quot;Require-LDAPS-On-Connection&quot;</A>
+can not be enabled for this server. You must disable this feature in
+order to use
+<A HREF="h_config_ldap_opts_ldaps">
+&quot;Require-LDAPS-On-Connection&quot;</A>
+<P>
&lt;End of help on this topic&gt;
</BODY>
</HTML>
@@ -14897,6 +14909,35 @@ When connecting to this server Alpine will attempt to use TLS encryption
on the connection.
If the StartTLS operation fails then the connection will not be used.
<P>
+Note that if this option is set, then
+<A HREF="h_config_ldap_opts_ldaps">
+&quot;Require-LDAPS-On-Connection&quot;</A>
+can not be enabled for this server. You must disable this feature in
+order to use
+<A HREF="h_config_ldap_opts_ldaps">
+&quot;Require-LDAPS-On-Connection&quot;</A>
+<P>
+&lt;End of help on this topic&gt;
+</BODY>
+</HTML>
+======= h_config_ldap_opts_ldaps =======
+<HTML>
+<HEAD>
+<TITLE>LDAP FEATURE: Require-LDAPS-On-Connection</TITLE>
+</HEAD>
+<BODY>
+<H1>LDAP FEATURE: Require-LDAPS-On-Connection</H1>
+
+When connecting to this server Alpine will use LDAPS (LDAP over SSL/TLS)
+on the connection.
+<P>
+This feature can not be used along with
+<A HREF="h_config_ldap_opts_tlsmust">&quot;Require-TLS-On-Connection&quot;</A>
+ or
+<A HREF="h_config_ldap_opts_tls">&quot;Attempt-TLS-On-Connection&quot;</A>.
+If you want to connect using StartTLS to this server, you must disable
+this feature first.
+<P>
&lt;End of help on this topic&gt;
</BODY>
</HTML>