From: jmatthew Date: Tue, 30 May 2017 09:33:31 +0000 (+0000) Subject: Teach ypldap to use tls when connecting to ldap servers. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=328147611064cec44a14d1be1ad8b9e0ef0b2546;p=openbsd Teach ypldap to use tls when connecting to ldap servers. libtls help from jsing@, linker help from deraadt@ --- diff --git a/usr.sbin/ypldap/Makefile b/usr.sbin/ypldap/Makefile index 6339334c159..178ffb1b744 100644 --- a/usr.sbin/ypldap/Makefile +++ b/usr.sbin/ypldap/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.8 2015/09/09 15:33:18 deraadt Exp $ +# $OpenBSD: Makefile,v 1.9 2017/05/30 09:33:31 jmatthew Exp $ PROG= ypldap SRCS= parse.y ypldap.c log.c \ @@ -8,8 +8,9 @@ SRCS= parse.y ypldap.c log.c \ MAN= ypldap.8 ypldap.conf.5 -DPADD= ${LIBEVENT} ${LIBUTIL} ${LIBRPCSVC} -LDADD= -levent -lutil -lrpcsvc +DPADD= ${LIBTLS} ${LIBSSL} ${LIBCRYPTO} ${LIBEVENT} ${LIBUTIL} \ + ${LIBRPCSVC} +LDADD= -ltls -lssl -lcrypto -levent -lutil -lrpcsvc CFLAGS+= -I${.CURDIR} CFLAGS+= -Wall CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes diff --git a/usr.sbin/ypldap/aldap.c b/usr.sbin/ypldap/aldap.c index 8e2d8a6fac6..e1092c74a36 100644 --- a/usr.sbin/ypldap/aldap.c +++ b/usr.sbin/ypldap/aldap.c @@ -1,5 +1,5 @@ -/* $Id: aldap.c,v 1.36 2017/03/27 04:46:47 jmatthew Exp $ */ -/* $OpenBSD: aldap.c,v 1.36 2017/03/27 04:46:47 jmatthew Exp $ */ +/* $Id: aldap.c,v 1.37 2017/05/30 09:33:31 jmatthew Exp $ */ +/* $OpenBSD: aldap.c,v 1.37 2017/05/30 09:33:31 jmatthew Exp $ */ /* * Copyright (c) 2008 Alexander Schrijver @@ -26,6 +26,8 @@ #include #include +#include + #include "aldap.h" #if 0 @@ -43,6 +45,9 @@ static int isu8cont(unsigned char); char *parseval(char *, size_t); int aldap_create_page_control(struct ber_element *, int, struct aldap_page_control *); +int aldap_send(struct aldap *, + struct ber_element *); +unsigned long aldap_application(struct ber_element *); #ifdef DEBUG void ldap_debug_elements(struct ber_element *); @@ -56,13 +61,21 @@ void ldap_debug_elements(struct ber_element *); #define LDAP_DEBUG(x, y) do { } while (0) #endif +unsigned long +aldap_application(struct ber_element *elm) +{ + return BER_TYPE_OCTETSTRING; +} + int aldap_close(struct aldap *al) { - if (close(al->ber.fd) == -1) - return (-1); + if (al->fd != -1) + if (close(al->ber.fd) == -1) + return (-1); ber_free(&al->ber); + evbuffer_free(al->buf); free(al); return (0); @@ -75,16 +88,110 @@ aldap_init(int fd) if ((a = calloc(1, sizeof(*a))) == NULL) return NULL; - a->ber.fd = fd; + a->buf = evbuffer_new(); + a->fd = fd; + a->ber.fd = -1; + ber_set_application(&a->ber, aldap_application); return a; } +int +aldap_tls(struct aldap *ldap, struct tls_config *cfg, const char *name) +{ + ldap->tls = tls_client(); + if (ldap->tls == NULL) { + ldap->err = ALDAP_ERR_OPERATION_FAILED; + return (-1); + } + + if (tls_configure(ldap->tls, cfg) == -1) { + ldap->err = ALDAP_ERR_TLS_ERROR; + return (-1); + } + + if (tls_connect_socket(ldap->tls, ldap->fd, name) == -1) { + ldap->err = ALDAP_ERR_TLS_ERROR; + return (-1); + } + + if (tls_handshake(ldap->tls) == -1) { + ldap->err = ALDAP_ERR_TLS_ERROR; + return (-1); + } + + ldap->fd = -1; + return (0); +} + +int +aldap_send(struct aldap *ldap, struct ber_element *root) +{ + int error, wrote; + void *ptr; + char *data; + size_t len, done; + + len = ber_calc_len(root); + error = ber_write_elements(&ldap->ber, root); + ber_free_elements(root); + if (error == -1) + return -1; + + ber_get_writebuf(&ldap->ber, &ptr); + done = 0; + data = ptr; + while (len > 0) { + if (ldap->tls != NULL) { + wrote = tls_write(ldap->tls, data + done, len); + if (wrote == TLS_WANT_POLLIN || + wrote == TLS_WANT_POLLOUT) + continue; + } else + wrote = write(ldap->fd, data + done, len); + + if (wrote == -1) + return -1; + + len -= wrote; + done += wrote; + } + + return 0; +} + +int +aldap_req_starttls(struct aldap *ldap) +{ + struct ber_element *root = NULL, *ber; + + if ((root = ber_add_sequence(NULL)) == NULL) + goto fail; + + ber = ber_printf_elements(root, "d{tst", ++ldap->msgid, BER_CLASS_APP, + (unsigned long) LDAP_REQ_EXTENDED, LDAP_STARTTLS_OID, + BER_CLASS_CONTEXT, (unsigned long) 0); + if (ber == NULL) { + ldap->err = ALDAP_ERR_OPERATION_FAILED; + goto fail; + } + + if (aldap_send(ldap, root) == -1) + goto fail; + + return (ldap->msgid); +fail: + if (root != NULL) + ber_free_elements(root); + + ldap->err = ALDAP_ERR_OPERATION_FAILED; + return (-1); +} + int aldap_bind(struct aldap *ldap, char *binddn, char *bindcred) { struct ber_element *root = NULL, *elm; - int error; if (binddn == NULL) binddn = ""; @@ -102,12 +209,10 @@ aldap_bind(struct aldap *ldap, char *binddn, char *bindcred) LDAP_DEBUG("aldap_bind", root); - error = ber_write_elements(&ldap->ber, root); - ber_free_elements(root); - root = NULL; - if (error == -1) + if (aldap_send(ldap, root) == -1) { + root = NULL; goto fail; - + } return (ldap->msgid); fail: if (root != NULL) @@ -121,7 +226,6 @@ int aldap_unbind(struct aldap *ldap) { struct ber_element *root = NULL, *elm; - int error; if ((root = ber_add_sequence(NULL)) == NULL) goto fail; @@ -132,12 +236,10 @@ aldap_unbind(struct aldap *ldap) LDAP_DEBUG("aldap_unbind", root); - error = ber_write_elements(&ldap->ber, root); - ber_free_elements(root); - root = NULL; - if (error == -1) + if (aldap_send(ldap, root) == -1) { + root = NULL; goto fail; - + } return (ldap->msgid); fail: if (root != NULL) @@ -154,7 +256,7 @@ aldap_search(struct aldap *ldap, char *basedn, enum scope scope, char *filter, struct aldap_page_control *page) { struct ber_element *root = NULL, *ber, *c; - int i, error; + int i; if ((root = ber_add_sequence(NULL)) == NULL) goto fail; @@ -192,10 +294,8 @@ aldap_search(struct aldap *ldap, char *basedn, enum scope scope, char *filter, LDAP_DEBUG("aldap_search", root); - error = ber_write_elements(&ldap->ber, root); - ber_free_elements(root); - root = NULL; - if (error == -1) { + if (aldap_send(ldap, root) == -1) { + root = NULL; ldap->err = ALDAP_ERR_OPERATION_FAILED; goto fail; } @@ -256,12 +356,44 @@ aldap_parse(struct aldap *ldap) long long msgid = 0; struct aldap_message *m; struct ber_element *a = NULL, *ep; + char rbuf[512]; + int ret, retry; if ((m = calloc(1, sizeof(struct aldap_message))) == NULL) return NULL; - if ((m->msg = ber_read_elements(&ldap->ber, NULL)) == NULL) - goto parsefail; + retry = 0; + while (m->msg == NULL) { + if (retry || EVBUFFER_LENGTH(ldap->buf) == 0) { + if (ldap->tls) { + ret = tls_read(ldap->tls, rbuf, sizeof(rbuf)); + if (ret == TLS_WANT_POLLIN || + ret == TLS_WANT_POLLOUT) + continue; + } else + ret = read(ldap->fd, rbuf, sizeof(rbuf)); + + if (ret == -1) { + goto parsefail; + } + + evbuffer_add(ldap->buf, rbuf, ret); + } + + if (EVBUFFER_LENGTH(ldap->buf) > 0) { + ber_set_readbuf(&ldap->ber, EVBUFFER_DATA(ldap->buf), + EVBUFFER_LENGTH(ldap->buf)); + errno = 0; + m->msg = ber_read_elements(&ldap->ber, NULL); + if (errno != 0 && errno != ECANCELED) { + goto parsefail; + } + + retry = 1; + } + } + + evbuffer_drain(ldap->buf, ldap->ber.br_rptr - ldap->ber.br_rbuf); LDAP_DEBUG("message", m->msg); @@ -304,10 +436,17 @@ aldap_parse(struct aldap *ldap) if (ber_scanf_elements(m->protocol_op, "{e", &m->references) != 0) goto parsefail; break; + case LDAP_RES_EXTENDED: + if (ber_scanf_elements(m->protocol_op, "{E", + &m->body.res.rescode) != 0) { + goto parsefail; + } + break; } return m; parsefail: + evbuffer_drain(ldap->buf, EVBUFFER_LENGTH(ldap->buf)); ldap->err = ALDAP_ERR_PARSER_ERROR; aldap_freemsg(m); return NULL; @@ -1241,6 +1380,9 @@ aldap_get_errno(struct aldap *a, const char **estr) case ALDAP_ERR_OPERATION_FAILED: *estr = "operation failed"; break; + case ALDAP_ERR_TLS_ERROR: + *estr = tls_error(a->tls); + break; default: *estr = "unknown"; break; diff --git a/usr.sbin/ypldap/aldap.h b/usr.sbin/ypldap/aldap.h index 8e3a7d8088c..0ee6202c3fc 100644 --- a/usr.sbin/ypldap/aldap.h +++ b/usr.sbin/ypldap/aldap.h @@ -1,5 +1,5 @@ -/* $Id: aldap.h,v 1.9 2012/04/30 21:40:03 jmatthew Exp $ */ -/* $OpenBSD: aldap.h,v 1.9 2012/04/30 21:40:03 jmatthew Exp $ */ +/* $Id: aldap.h,v 1.10 2017/05/30 09:33:31 jmatthew Exp $ */ +/* $OpenBSD: aldap.h,v 1.10 2017/05/30 09:33:31 jmatthew Exp $ */ /* * Copyright (c) 2008 Alexander Schrijver @@ -19,20 +19,31 @@ */ #include + +#include + #include "ber.h" -#define LDAP_URL "ldap://" -#define LDAP_PORT 389 -#define LDAP_PAGED_OID "1.2.840.113556.1.4.319" +#define LDAP_URL "ldap://" +#define LDAP_PORT 389 +#define LDAPS_PORT 636 +#define LDAP_PAGED_OID "1.2.840.113556.1.4.319" +#define LDAP_STARTTLS_OID "1.3.6.1.4.1.1466.20037" struct aldap { #define ALDAP_ERR_SUCCESS 0 #define ALDAP_ERR_PARSER_ERROR 1 #define ALDAP_ERR_INVALID_FILTER 2 #define ALDAP_ERR_OPERATION_FAILED 3 +#define ALDAP_ERR_TLS_ERROR 4 u_int8_t err; int msgid; struct ber ber; + + int fd; + struct tls *tls; + + struct evbuffer *buf; }; struct aldap_page_control { @@ -103,6 +114,9 @@ enum protocol_op { LDAP_REQ_ABANDON_30 = 16, LDAP_RES_SEARCH_REFERENCE = 19, + + LDAP_REQ_EXTENDED = 23, + LDAP_RES_EXTENDED = 24 }; enum deref_aliases { @@ -189,11 +203,15 @@ enum subfilter { LDAP_FILT_SUBS_FIN = 2, }; -struct aldap *aldap_init(int fd); +struct aldap *aldap_init(int); +int aldap_tls(struct aldap *, struct tls_config *, + const char *); int aldap_close(struct aldap *); struct aldap_message *aldap_parse(struct aldap *); void aldap_freemsg(struct aldap_message *); +int aldap_req_starttls(struct aldap *); + int aldap_bind(struct aldap *, char *, char *); int aldap_unbind(struct aldap *); int aldap_search(struct aldap *, char *, enum scope, char *, char **, int, int, int, struct aldap_page_control *); diff --git a/usr.sbin/ypldap/ldapclient.c b/usr.sbin/ypldap/ldapclient.c index dbaae8b4aff..57bcb31e520 100644 --- a/usr.sbin/ypldap/ldapclient.c +++ b/usr.sbin/ypldap/ldapclient.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ldapclient.c,v 1.38 2017/01/20 12:39:36 benno Exp $ */ +/* $OpenBSD: ldapclient.c,v 1.39 2017/05/30 09:33:31 jmatthew Exp $ */ /* * Copyright (c) 2008 Alexander Schrijver @@ -84,6 +84,7 @@ client_aldap_open(struct ypldap_addr_list *addr) warn("connect to %s port %s (%s) failed", hbuf, sbuf, "tcp"); close(fd); + fd = -1; } if (fd == -1) @@ -97,20 +98,28 @@ client_addr_init(struct idm *idm) { struct sockaddr_in *sa_in; struct sockaddr_in6 *sa_in6; - struct ypldap_addr *h; + struct ypldap_addr *h; + int defport; + + if (idm->idm_port != 0) + defport = idm->idm_port; + else if (idm->idm_flags & F_SSL) + defport = LDAPS_PORT; + else + defport = LDAP_PORT; TAILQ_FOREACH(h, &idm->idm_addr, next) { switch (h->ss.ss_family) { case AF_INET: sa_in = (struct sockaddr_in *)&h->ss; if (ntohs(sa_in->sin_port) == 0) - sa_in->sin_port = htons(LDAP_PORT); + sa_in->sin_port = htons(defport); idm->idm_state = STATE_DNS_DONE; break; case AF_INET6: sa_in6 = (struct sockaddr_in6 *)&h->ss; if (ntohs(sa_in6->sin6_port) == 0) - sa_in6->sin6_port = htons(LDAP_PORT); + sa_in6->sin6_port = htons(defport); idm->idm_state = STATE_DNS_DONE; break; default: @@ -584,6 +593,39 @@ client_try_idm(struct env *env, struct idm *idm) if ((al = client_aldap_open(&idm->idm_addr)) == NULL) return (-1); + if (idm->idm_flags & F_STARTTLS) { + log_debug("requesting starttls"); + where = "starttls"; + if (aldap_req_starttls(al) == -1) + goto bad; + + where = "parsing"; + if ((m = aldap_parse(al)) == NULL) + goto bad; + where = "verifying msgid"; + if (al->msgid != m->msgid) { + aldap_freemsg(m); + goto bad; + } + where = "starttls result"; + if (aldap_get_resultcode(m) != LDAP_SUCCESS) { + aldap_freemsg(m); + goto bad; + } + aldap_freemsg(m); + } + + if (idm->idm_flags & (F_STARTTLS | F_SSL)) { + log_debug("starting tls"); + where = "enabling tls"; + if (aldap_tls(al, idm->idm_tls_config, idm->idm_name) < 0) { + const char *err; + aldap_get_errno(al, &err); + log_debug("tls failed: %s", err); + goto bad; + } + } + if (idm->idm_flags & F_NEEDAUTH) { where = "binding"; if (aldap_bind(al, idm->idm_binddn, idm->idm_bindcred) == -1) diff --git a/usr.sbin/ypldap/parse.y b/usr.sbin/ypldap/parse.y index e0a8a6e22f3..9dc32c8f544 100644 --- a/usr.sbin/ypldap/parse.y +++ b/usr.sbin/ypldap/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.21 2017/01/05 13:53:10 krw Exp $ */ +/* $OpenBSD: parse.y,v 1.22 2017/05/30 09:33:31 jmatthew Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard @@ -101,11 +101,12 @@ typedef struct { %token SERVER FILTER ATTRIBUTE BASEDN BINDDN GROUPDN BINDCRED MAPS CHANGE DOMAIN PROVIDE %token USER GROUP TO EXPIRE HOME SHELL GECOS UID GID INTERVAL %token PASSWD NAME FIXED LIST GROUPNAME GROUPPASSWD GROUPGID MAP -%token INCLUDE DIRECTORY CLASS PORT ERROR GROUPMEMBERS +%token INCLUDE DIRECTORY CLASS PORT ERROR GROUPMEMBERS LDAPS TLS CAFILE %token STRING %token NUMBER %type opcode attribute -%type port +%type port +%type ssl %% @@ -157,8 +158,28 @@ varset : STRING '=' STRING { } ; -port : /* empty */ { $$ = NULL; } - | PORT STRING { $$ = $2; } +port : PORT STRING { + struct servent *servent; + + servent = getservbyname($2, "tcp"); + if (servent == NULL) { + yyerror("port %s is invalid", $2); + free($2); + YYERROR; + } + $$ = ntohs(servent->s_port); + free($2); + } + | PORT NUMBER { + if ($2 <= 0 || $2 >= (int)USHRT_MAX) { + yyerror("invalid port: %lld", $2); + YYERROR; + } + $$ = $2; + } + | /* empty */ { + $$ = 0; + } ; opcode : GROUP { $$ = 0; } @@ -268,7 +289,12 @@ diropt : BINDDN STRING { } ; -directory : DIRECTORY STRING port { +ssl : /* empty */ { $$ = 0; } + | LDAPS { $$ = F_SSL; } + | TLS { $$ = F_STARTTLS; } + ; + +directory : DIRECTORY STRING port ssl { if ((idm = calloc(1, sizeof(*idm))) == NULL) fatal(NULL); idm->idm_id = conf->sc_maxid++; @@ -280,8 +306,54 @@ directory : DIRECTORY STRING port { free($2); YYERROR; } - free($2); + + idm->idm_port = $3; + + if ($4 != 0) { + if (tls_init()) { + yyerror("tls init failed"); + YYERROR; + } + + idm->idm_flags |= $4; + idm->idm_tls_config = tls_config_new(); + if (idm->idm_tls_config == NULL) { + yyerror("tls config failed"); + YYERROR; + } + + if (tls_config_set_protocols( + idm->idm_tls_config, + TLS_PROTOCOLS_ALL) == -1) { + yyerror("tls set protocols failed: %s", + tls_config_error( + idm->idm_tls_config)); + tls_config_free(idm->idm_tls_config); + idm->idm_tls_config = NULL; + YYERROR; + } + if (tls_config_set_ciphers(idm->idm_tls_config, + "compat") == -1) { + yyerror("tls set ciphers failed: %s", + tls_config_error( + idm->idm_tls_config)); + tls_config_free(idm->idm_tls_config); + idm->idm_tls_config = NULL; + YYERROR; + } + + if (tls_config_set_ca_file(idm->idm_tls_config, + conf->sc_cafile) == -1) { + yyerror("tls set CA bundle failed: %s", + tls_config_error( + idm->idm_tls_config)); + tls_config_free(idm->idm_tls_config); + idm->idm_tls_config = NULL; + YYERROR; + } + } + } '{' optnl diropts '}' { TAILQ_INSERT_TAIL(&conf->sc_idms, idm, idm_entry); idm = NULL; @@ -324,6 +396,10 @@ main : INTERVAL NUMBER { } free($3); } + | CAFILE STRING { + free(conf->sc_cafile); + conf->sc_cafile = $2; + } ; diropts : diropts diropt nl @@ -368,6 +444,7 @@ lookup(char *s) { "basedn", BASEDN }, { "bindcred", BINDCRED }, { "binddn", BINDDN }, + { "cafile", CAFILE }, { "change", CHANGE }, { "class", CLASS }, { "directory", DIRECTORY }, @@ -386,6 +463,7 @@ lookup(char *s) { "home", HOME }, { "include", INCLUDE }, { "interval", INTERVAL }, + { "ldaps", LDAPS }, { "list", LIST }, { "map", MAP }, { "maps", MAPS }, @@ -395,6 +473,7 @@ lookup(char *s) { "provide", PROVIDE }, { "server", SERVER }, { "shell", SHELL }, + { "tls", TLS }, { "to", TO }, { "uid", UID }, { "user", USER }, @@ -731,6 +810,11 @@ parse_config(struct env *x_conf, const char *filename, int opts) TAILQ_INIT(&conf->sc_idms); conf->sc_conf_tv.tv_sec = DEFAULT_INTERVAL; conf->sc_conf_tv.tv_usec = 0; + conf->sc_cafile = strdup(YPLDAP_CERT_FILE); + if (conf->sc_cafile == NULL) { + log_warn("malloc"); + return (-1); + } errors = 0; diff --git a/usr.sbin/ypldap/ypldap.conf.5 b/usr.sbin/ypldap/ypldap.conf.5 index 386368bfa36..656b7600128 100644 --- a/usr.sbin/ypldap/ypldap.conf.5 +++ b/usr.sbin/ypldap/ypldap.conf.5 @@ -1,4 +1,4 @@ -.\" $OpenBSD: ypldap.conf.5,v 1.19 2012/04/30 11:28:25 jmatthew Exp $ +.\" $OpenBSD: ypldap.conf.5,v 1.20 2017/05/30 09:33:31 jmatthew Exp $ .\" .\" Copyright (c) 2008 Pierre-Yves Ritschard .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: April 30 2012 $ +.Dd $Mdocdate: May 30 2017 $ .Dt YPLDAP.CONF 5 .Os .Sh NAME @@ -52,7 +52,6 @@ Macros are not expanded inside quotes. .Pp For example: .Bd -literal -offset indent - fixed_gecos="Pulled from LDAP" fixed attribute gecos $fixed_gecos @@ -73,6 +72,10 @@ Specify a map that should be provided by .Nm The currently implemented maps are: passwd.byname, passwd.byuid, group.byname, group.bygid. +.It Ic cafile Ar filename +Load CA certificates from the specified file to validate the server certificate. +If not specified, CA certificates will be loaded from +.Pa /etc/ssl/cert.pem . .El .Sh DIRECTORIES Directories are used to describe the LDAP schema and help @@ -83,11 +86,23 @@ convert LDAP entries to and .Xr group 5 lines. -A directory declaration is of the following form: -.Bd -literal -offset indent -directory "some.host" { - # directives -} +Each directory section consists of a declaration of the directory +server name and a set of directives describing how entries from the +directory are used to construct YP map entries. +.Bl -tag -width Ds +.It Ic directory Ar hostname Oo Ic port Ar port Oc Oo tls Oc Brq ... +Defines a directory by hostname and optionally port number. +If the +.Ar tls +argument is not specified, no transport-level security will be used. +Valid options are: +.Bl -tag -width Ds +.It Ic tls +Use STARTTLS to negotiate TLS, by default on port 389. +.It Ic ldaps +Connect with TLS enabled, by default on port 636. +.El +.El .Ed .Pp Valid directives for directories are: diff --git a/usr.sbin/ypldap/ypldap.h b/usr.sbin/ypldap/ypldap.h index 8ee722217cc..690366386b0 100644 --- a/usr.sbin/ypldap/ypldap.h +++ b/usr.sbin/ypldap/ypldap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ypldap.h,v 1.18 2017/01/20 12:39:36 benno Exp $ */ +/* $OpenBSD: ypldap.h,v 1.19 2017/05/30 09:33:31 jmatthew Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard @@ -17,9 +17,11 @@ */ #include +#include #define YPLDAP_USER "_ypldap" #define YPLDAP_CONF_FILE "/etc/ypldap.conf" +#define YPLDAP_CERT_FILE "/etc/ssl/cert.pem" #define DEFAULT_INTERVAL 600 #define LINE_WIDTH 1024 #define FILTER_WIDTH 128 @@ -91,6 +93,7 @@ struct idm { #define F_SSL 0x00100000 #define F_CONFIGURING 0x00200000 #define F_NEEDAUTH 0x00400000 +#define F_STARTTLS 0x00800000 #define F_FIXED_ATTR(n) (1<