diff options
-rw-r--r-- | usr.sbin/ypldap/aldap.c | 21 | ||||
-rw-r--r-- | usr.sbin/ypldap/aldap.h | 6 | ||||
-rw-r--r-- | usr.sbin/ypldap/ldapclient.c | 407 | ||||
-rw-r--r-- | usr.sbin/ypldap/parse.y | 19 | ||||
-rw-r--r-- | usr.sbin/ypldap/ypldap.h | 3 |
5 files changed, 348 insertions, 108 deletions
diff --git a/usr.sbin/ypldap/aldap.c b/usr.sbin/ypldap/aldap.c index b8cb3ec0e6a..c2b69a7c5c1 100644 --- a/usr.sbin/ypldap/aldap.c +++ b/usr.sbin/ypldap/aldap.c @@ -1,5 +1,5 @@ -/* $Id: aldap.c,v 1.4 2008/10/06 08:01:28 aschrijver Exp $ */ -/* $OpenBSD: aldap.c,v 1.4 2008/10/06 08:01:28 aschrijver Exp $ */ +/* $Id: aldap.c,v 1.5 2008/10/14 21:41:03 aschrijver Exp $ */ +/* $OpenBSD: aldap.c,v 1.5 2008/10/14 21:41:03 aschrijver Exp $ */ /* * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org> @@ -156,7 +156,7 @@ aldap_parse(struct aldap *ldap) &m->body.res.rescode, &m->dn, &m->body.res.diagmsg, &a) != 0) goto parsefail; if(m->body.res.rescode == LDAP_REFERRAL) - if(ber_scanf_elements(a, "{e", &m->body.references) != 0) + if(ber_scanf_elements(a, "{e", &m->references) != 0) goto parsefail; break; case LDAP_RES_SEARCH_ENTRY: @@ -165,7 +165,7 @@ aldap_parse(struct aldap *ldap) goto parsefail; break; case LDAP_RES_SEARCH_REFERENCE: - if(ber_scanf_elements(m->protocol_op, "{e", &m->body.references) != 0) + if(ber_scanf_elements(m->protocol_op, "{e", &m->references) != 0) goto parsefail; break; } @@ -205,7 +205,9 @@ aldap_get_dn(struct aldap_message *msg) char ** aldap_get_references(struct aldap_message *msg) { - return aldap_get_stringset(msg->body.references); + if(msg->references == NULL) + return NULL; + return aldap_get_stringset(msg->references); } void @@ -387,7 +389,8 @@ aldap_parse_url(char *url, struct aldap_url *lu) *forward2 = '\0'; /* if a port is given */ if(*(forward2+1) != '\0') { - lu->port = strtonum(++forward2, 0, sizeof(lu->port), &errstr); +#define PORT_MAX UINT16_MAX + lu->port = strtonum(++forward2, 0, PORT_MAX, &errstr); if(errstr) goto fail; } @@ -478,9 +481,11 @@ aldap_get_stringset(struct ber_element *elm) if(elm->be_type != BER_TYPE_OCTETSTRING) return NULL; - for(a = elm, i = 1; i > 0 && a->be_type == BER_TYPE_OCTETSTRING; - a = a->be_next, i++) + for(a = elm, i = 1; i > 0 && a != NULL && a->be_type == + BER_TYPE_OCTETSTRING; a = a->be_next, i++) ; + if(i == 1) + return NULL; if((ret = calloc(i + 1, sizeof(char *))) == NULL) return NULL; diff --git a/usr.sbin/ypldap/aldap.h b/usr.sbin/ypldap/aldap.h index d27feb76c5e..5619d7dfec7 100644 --- a/usr.sbin/ypldap/aldap.h +++ b/usr.sbin/ypldap/aldap.h @@ -1,5 +1,5 @@ -/* $Id: aldap.h,v 1.3 2008/10/06 11:20:20 aschrijver Exp $ */ -/* $OpenBSD: aldap.h,v 1.3 2008/10/06 11:20:20 aschrijver Exp $ */ +/* $Id: aldap.h,v 1.4 2008/10/14 21:41:03 aschrijver Exp $ */ +/* $OpenBSD: aldap.h,v 1.4 2008/10/14 21:41:03 aschrijver Exp $ */ /* * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org> @@ -49,8 +49,8 @@ struct aldap_message { struct ber_element *iter; struct ber_element *entries; } search; - struct ber_element *references; } body; + struct ber_element *references; }; enum aldap_protocol { diff --git a/usr.sbin/ypldap/ldapclient.c b/usr.sbin/ypldap/ldapclient.c index 1f812bc59ac..ac366464e28 100644 --- a/usr.sbin/ypldap/ldapclient.c +++ b/usr.sbin/ypldap/ldapclient.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ldapclient.c,v 1.4 2008/10/06 11:20:20 aschrijver Exp $ */ +/* $OpenBSD: ldapclient.c,v 1.5 2008/10/14 21:41:03 aschrijver Exp $ */ /* * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org> @@ -37,9 +37,7 @@ #include <stdlib.h> #include <string.h> -#define LDAP_DEPRECATED 1 #include "aldap.h" - #include "ypldap.h" void client_sig_handler(int, short, void *); @@ -52,35 +50,69 @@ int client_try_idm(struct env *, struct idm *); void client_try_idm_wrapper(int, short, void *); void client_try_server_wrapper(int, short, void *); -static int remote_connect(const char *, const char *, struct addrinfo); +int do_build_group(struct env *, struct idm *, struct aldap *, char *, enum + scope, char *); +int do_build_passwd(struct env *, struct idm *, struct aldap *, char *, enum + scope, char *); + +struct aldap *aldap_open(char *, char *); +int aldap_close(struct aldap *); +struct aldap *connect_to_referral(struct aldap_message *, struct aldap_url *); -static int -remote_connect(const char *host, const char *port, struct addrinfo hints) +int +aldap_close(struct aldap *al) { + if(close(al->ber.fd) == -1) + return (-1); + + free(al); + + return (0); +} + +struct aldap * +aldap_open(char *host, char *port) +{ + struct addrinfo hints; + struct aldap *al; + int fd; + struct addrinfo *res, *res0; - int s, error; + int error; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + log_debug("trying directory: %s", host); if ((error = getaddrinfo(host, port, &hints, &res))) errx(1, "getaddrinfo: %s", gai_strerror(error)); res0 = res; do { - if ((s = socket(res0->ai_family, res0->ai_socktype, + if ((fd = socket(res0->ai_family, res0->ai_socktype, res0->ai_protocol)) < 0) continue; - if (connect(s, res0->ai_addr, res0->ai_addrlen) == 0) + if (connect(fd, res0->ai_addr, res0->ai_addrlen) == 0) break; - else + else { warn("connect to %s port %s (%s) failed", host, port, "tcp"); + return NULL; + } - close(s); - s = -1; + close(fd); + fd = -1; } while ((res0 = res0->ai_next) != NULL); freeaddrinfo(res); - return (s); + if((al = aldap_init(fd)) == NULL) + return NULL; + + return al; } void @@ -263,160 +295,351 @@ client_configure_wrapper(int fd, short event, void *p) client_configure(env); } -int -client_try_idm(struct env *env, struct idm *idm) +struct aldap * +connect_to_referral(struct aldap_message *m, struct aldap_url *lu) { - int i, j, fd; - char *attrs[ATTR_MAX+1]; - char **ldap_attrs; - const char *where; - struct idm_req ir; - struct addrinfo hints; - struct aldap_message *m; - struct aldap *al; + int i; + char **refs, *port; + struct aldap *al = NULL; - log_debug("trying directory: %s", idm->idm_name); + if((refs = aldap_get_references(m)) == NULL) + return NULL; - bzero(&ir, sizeof(ir)); - imsg_compose(env->sc_ibuf, IMSG_START_UPDATE, 0, 0, &ir, sizeof(ir)); + for(i = 0; i >= 0 && refs[i] != NULL; i++) { + aldap_parse_url(refs[i], lu); + asprintf(&port, "%d", lu->port ? lu->port : 389); - /* connect to LDAP server */ - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; + if((al = aldap_open(lu->host, port)) != NULL) { + free(port); + break; + } - where = "connect"; - fd = remote_connect(idm->idm_name, "389", hints); - if(fd == -1) - goto bad; + free(port); + } - al = aldap_init(fd); - if(al == NULL) - goto bad; + aldap_free_references(refs); - /* do a bind request */ - if(aldap_bind(al, idm->idm_binddn, idm->idm_bindcred) == -1) - goto bad; - where = "parsing"; - if((m = aldap_parse(al)) == NULL) - goto bad; - if(al->msgid != m->msgid) - goto bad; /* XXX: error reporting */ - aldap_freemsg(m); + return al; +} + +#define MAX_REFERRALS 10 +int +do_build_group(struct env *env, struct idm *idm, struct aldap *al, char + *basedn, enum scope scope, char *filter) +{ + char *attrs[ATTR_MAX+1]; + char **ldap_attrs; + struct idm_req ir; + struct aldap_message *m; + struct aldap_url lu; + struct aldap *al_ref; + int i, j, k; + const char *where; + static int refcnt = 0; bzero(attrs, sizeof(attrs)); - for (i = 0, j = 0; i < ATTR_MAX; i++) { + for (i = ATTR_GR_MIN, j = 0; i < ATTR_GR_MAX; i++) { if (idm->idm_flags & F_FIXED_ATTR(i)) continue; attrs[j++] = idm->idm_attrs[i]; } attrs[j] = NULL; - /* do a search request */ - aldap_search(al, idm->idm_basedn, LDAP_SCOPE_SUBTREE, - idm->idm_filters[FILTER_USER], attrs, 0, 0, 0); + where = "search"; + if(aldap_search(al, basedn, scope, filter, attrs, 0, 0, 0) == -1) + goto bad; /* - * build password line. + * build group line. */ while((m = aldap_parse(al)) != NULL) { - if(al->msgid != m->msgid) - goto bad; /* XXX: error reporting */ - if (m->message_type == LDAP_RES_SEARCH_RESULT) + where = "verifying msgid"; + if(al->msgid != m->msgid) { + aldap_freemsg(m); + goto bad; + } + /* continuation referral */ + if (m->message_type == LDAP_RES_SEARCH_REFERENCE) { + if(refcnt++ >= MAX_REFERRALS) + goto next_entry; + + if((al_ref = connect_to_referral(m, &lu)) == NULL) + goto next_entry; + do_build_group(env, idm, al_ref, lu.dn, + lu.scope, idm->idm_filters[FILTER_GROUP]); + aldap_close(al_ref); + goto next_entry; + } + /* normal referral */ + if(m->message_type == LDAP_RES_SEARCH_RESULT && + aldap_get_resultcode(m) == LDAP_REFERRAL) { + if(refcnt++ == MAX_REFERRALS) { + aldap_freemsg(m); + break; + } + + if((al_ref = connect_to_referral(m, &lu)) == NULL) { + aldap_freemsg(m); + break; + } + do_build_group(env, idm, al_ref, lu.dn, + lu.scope, idm->idm_filters[FILTER_GROUP]); + aldap_close(al_ref); + } + /* end of the search result chain */ + if (m->message_type == LDAP_RES_SEARCH_RESULT) { + aldap_freemsg(m); break; + } + /* search entry; the rest we won't handle */ + if(m->message_type != LDAP_RES_SEARCH_ENTRY) { + aldap_freemsg(m); + goto bad; + } + /* search entry */ bzero(&ir, sizeof(ir)); - for (i = 0, j = 0; i < ATTR_MAX; i++) { + for (i = ATTR_GR_MIN, j = 0; i < ATTR_GR_MAX; i++) { if (idm->idm_flags & F_FIXED_ATTR(i)) { if (strlcat(ir.ir_line, idm->idm_attrs[i], sizeof(ir.ir_line)) >= sizeof(ir.ir_line)) /* * entry yields a line > 1024, trash it. */ - continue; - if (i == ATTR_UID) { - ir.ir_key.ik_uid = strtonum( + goto next_entry; + if (i == ATTR_GR_GID) { + ir.ir_key.ik_gid = strtonum( idm->idm_attrs[i], 0, - UID_MAX, NULL); + GID_MAX, NULL); } + } else if (idm->idm_list & F_LIST(i)) { + if (aldap_match_entry(m, attrs[j++], &ldap_attrs) == -1) + goto next_entry; + if (ldap_attrs == NULL || ldap_attrs[0] == NULL) + goto next_entry; + for(k = 0; k >= 0 && ldap_attrs[k] != NULL; k++) { + if (strlcat(ir.ir_line, ldap_attrs[k], + sizeof(ir.ir_line)) >= sizeof(ir.ir_line)) + continue; + if(ldap_attrs[k+1] != NULL) + if (strlcat(ir.ir_line, ",", + sizeof(ir.ir_line)) + >= sizeof(ir.ir_line)) { + aldap_free_entry(ldap_attrs); + goto next_entry; + } + } + aldap_free_entry(ldap_attrs); } else { - aldap_match_entry(m, attrs[j++], &ldap_attrs); + if(aldap_match_entry(m, attrs[j++], &ldap_attrs) == -1) + goto next_entry; if (ldap_attrs == NULL || ldap_attrs[0] == NULL) - continue; + goto next_entry; if (strlcat(ir.ir_line, ldap_attrs[0], - sizeof(ir.ir_line)) >= sizeof(ir.ir_line)) - continue; - if (i == ATTR_UID) { + sizeof(ir.ir_line)) >= sizeof(ir.ir_line)) { + aldap_free_entry(ldap_attrs); + goto next_entry; + } + if (i == ATTR_GR_GID) { ir.ir_key.ik_uid = strtonum( - ldap_attrs[0], 0, UID_MAX, NULL); + ldap_attrs[0], 0, GID_MAX, NULL); } aldap_free_entry(ldap_attrs); } - if (i != ATTR_SHELL) + if (i != ATTR_GR_MEMBERS) if (strlcat(ir.ir_line, ":", sizeof(ir.ir_line)) >= sizeof(ir.ir_line)) - continue; + goto next_entry; } - imsg_compose(env->sc_ibuf, IMSG_PW_ENTRY, 0, 0, + imsg_compose(env->sc_ibuf, IMSG_GRP_ENTRY, 0, 0, &ir, sizeof(ir)); +next_entry: + aldap_freemsg(m); } - /* - * exact same code but for groups. - */ + return (0); +bad: + log_debug("directory %s errored out in %s", idm->idm_name, where); + return (-1); +} + +int +do_build_passwd(struct env *env, struct idm *idm, struct aldap *al, char + *basedn, enum scope scope, char *filter) +{ + char *attrs[ATTR_MAX+1]; + char **ldap_attrs; + struct idm_req ir; + struct aldap_message *m; + struct aldap_url lu; + struct aldap *al_ref; + int i, j, k; + const char *where; + static int refcnt = 0; bzero(attrs, sizeof(attrs)); - for (i = ATTR_GR_MIN, j = 0; i < ATTR_GR_MAX; i++) { + for (i = 0, j = 0; i < ATTR_MAX; i++) { if (idm->idm_flags & F_FIXED_ATTR(i)) continue; attrs[j++] = idm->idm_attrs[i]; } attrs[j] = NULL; - aldap_search(al, idm->idm_basedn, LDAP_SCOPE_SUBTREE, - idm->idm_filters[FILTER_GROUP], attrs, 0, 0, 0); + where = "search"; + if(aldap_search(al, basedn, scope, filter, attrs, 0, 0, 0) == -1) + goto bad; + /* + * build password line. + */ while((m = aldap_parse(al)) != NULL) { - if(al->msgid != m->msgid) - goto bad; /* XXX: error reporting */ - if (m->message_type == LDAP_RES_SEARCH_RESULT) + where = "verifying msgid"; + if(al->msgid != m->msgid) { + aldap_freemsg(m); + goto bad; + } + /* continuation referral */ + if (m->message_type == LDAP_RES_SEARCH_REFERENCE) { + if(refcnt++ >= MAX_REFERRALS) + goto next_entry; + + if((al_ref = connect_to_referral(m, &lu)) == NULL) + goto next_entry; + do_build_passwd(env, idm, al_ref, lu.dn, + lu.scope, idm->idm_filters[FILTER_USER]); + aldap_close(al_ref); + goto next_entry; + } + /* normal referral */ + if(m->message_type == LDAP_RES_SEARCH_RESULT && + aldap_get_resultcode(m) == LDAP_REFERRAL) { + if(refcnt++ == MAX_REFERRALS) { + aldap_freemsg(m); + break; + } + + if((al_ref = connect_to_referral(m, &lu)) == NULL) { + aldap_freemsg(m); + break; + } + do_build_passwd(env, idm, al_ref, lu.dn, + lu.scope, idm->idm_filters[FILTER_USER]); + aldap_close(al_ref); + } + /* end of the search result chain */ + if (m->message_type == LDAP_RES_SEARCH_RESULT) { + aldap_freemsg(m); break; + } + /* search entry; the rest we won't handle */ + if(m->message_type != LDAP_RES_SEARCH_ENTRY) { + aldap_freemsg(m); + goto bad; + } + /* search entry */ bzero(&ir, sizeof(ir)); - for (i = ATTR_GR_MIN, j = 0; i < ATTR_GR_MAX; i++) { + for (i = 0, j = 0; i < ATTR_MAX; i++) { if (idm->idm_flags & F_FIXED_ATTR(i)) { if (strlcat(ir.ir_line, idm->idm_attrs[i], sizeof(ir.ir_line)) >= sizeof(ir.ir_line)) /* * entry yields a line > 1024, trash it. */ - continue; - if (i == ATTR_GR_GID) { - ir.ir_key.ik_gid = strtonum( + goto next_entry; + if (i == ATTR_UID) { + ir.ir_key.ik_uid = strtonum( idm->idm_attrs[i], 0, - GID_MAX, NULL); + UID_MAX, NULL); + } + } else if (idm->idm_list & F_LIST(i)) { + if (aldap_match_entry(m, attrs[j++], &ldap_attrs) == -1) + goto next_entry; + if (ldap_attrs == NULL || ldap_attrs[0] == NULL) + goto next_entry; + for(k = 0; k >= 0 && ldap_attrs[k] != NULL; k++) { + if (strlcat(ir.ir_line, ldap_attrs[k], + sizeof(ir.ir_line)) >= sizeof(ir.ir_line)) + continue; + if(ldap_attrs[k+1] != NULL) + if (strlcat(ir.ir_line, ",", + sizeof(ir.ir_line)) + >= sizeof(ir.ir_line)) { + aldap_free_entry(ldap_attrs); + goto next_entry; + } } + aldap_free_entry(ldap_attrs); } else { - aldap_match_entry(m, attrs[j++], &ldap_attrs); + if (aldap_match_entry(m, attrs[j++], &ldap_attrs) == -1) + goto next_entry; if (ldap_attrs == NULL || ldap_attrs[0] == NULL) - continue; + goto next_entry; if (strlcat(ir.ir_line, ldap_attrs[0], - sizeof(ir.ir_line)) >= sizeof(ir.ir_line)) - continue; - if (i == ATTR_GR_GID) { + sizeof(ir.ir_line)) >= sizeof(ir.ir_line)) { + aldap_free_entry(ldap_attrs); + goto next_entry; + } + if (i == ATTR_UID) { ir.ir_key.ik_uid = strtonum( - ldap_attrs[0], 0, GID_MAX, NULL); + ldap_attrs[0], 0, UID_MAX, NULL); } aldap_free_entry(ldap_attrs); } - if (i != ATTR_GR_MEMBERS) + if (i != ATTR_SHELL) if (strlcat(ir.ir_line, ":", sizeof(ir.ir_line)) >= sizeof(ir.ir_line)) - continue; + goto next_entry; } - imsg_compose(env->sc_ibuf, IMSG_GRP_ENTRY, 0, 0, + imsg_compose(env->sc_ibuf, IMSG_PW_ENTRY, 0, 0, &ir, sizeof(ir)); +next_entry: + aldap_freemsg(m); + } + + return (0); +bad: + log_debug("directory %s errored out in %s", idm->idm_name, where); + return (-1); +} + + +int +client_try_idm(struct env *env, struct idm *idm) +{ + const char *where; + struct idm_req ir; + struct aldap_message *m; + struct aldap *al; + + bzero(&ir, sizeof(ir)); + imsg_compose(env->sc_ibuf, IMSG_START_UPDATE, 0, 0, &ir, sizeof(ir)); + + where = "connect"; + if((al = aldap_open(idm->idm_name, "389")) == NULL) + goto bad; + + if (idm->idm_flags & F_NEEDAUTH) { + where = "binding"; + if(aldap_bind(al, idm->idm_binddn, idm->idm_bindcred) == -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; + } + aldap_freemsg(m); } + do_build_passwd(env, idm, al, idm->idm_basedn, LDAP_SCOPE_SUBTREE, + idm->idm_filters[FILTER_USER]); + do_build_group(env, idm, al, idm->idm_basedn, LDAP_SCOPE_SUBTREE, + idm->idm_filters[FILTER_GROUP]); + + aldap_close(al); + return (0); bad: log_debug("directory %s errored out in %s", idm->idm_name, where); diff --git a/usr.sbin/ypldap/parse.y b/usr.sbin/ypldap/parse.y index 8ee475028a6..dfab48c3c11 100644 --- a/usr.sbin/ypldap/parse.y +++ b/usr.sbin/ypldap/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.2 2008/09/30 16:24:16 aschrijver Exp $ */ +/* $OpenBSD: parse.y,v 1.3 2008/10/14 21:41:03 aschrijver Exp $ */ /* * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org> @@ -98,7 +98,7 @@ typedef struct { %token SERVER FILTER ATTRIBUTE BASEDN BINDDN BINDCRED MAPS CHANGE DOMAIN PROVIDE %token USER GROUP TO EXPIRE HOME SHELL GECOS UID GID INTERVAL -%token PASSWD NAME FIXED GROUPNAME GROUPPASSWD GROUPGID MAP +%token PASSWD NAME FIXED LIST GROUPNAME GROUPPASSWD GROUPGID MAP %token INCLUDE DIRECTORY CLASS PORT SSL ERROR GROUPMEMBERS %token <v.string> STRING %token <v.number> NUMBER @@ -196,11 +196,10 @@ diropt : BINDDN STRING { free($2); } | BASEDN STRING { - idm->idm_flags |= F_NEEDAUTH; if (strlcpy(idm->idm_basedn, $2, sizeof(idm->idm_basedn)) >= sizeof(idm->idm_basedn)) { - yyerror("directory bindcred truncated"); + yyerror("directory basedn truncated"); free($2); YYERROR; } @@ -237,6 +236,17 @@ diropt : BINDDN STRING { idm->idm_flags |= F_FIXED_ATTR($3); free($4); } + | LIST attribute MAPS TO STRING { + if (strlcpy(idm->idm_attrs[$2], $5, + sizeof(idm->idm_attrs[$2])) >= + sizeof(idm->idm_attrs[$2])) { + yyerror("attribute truncated"); + free($5); + YYERROR; + } + idm->idm_list |= F_LIST($2); + free($5); + } ; directory : DIRECTORY STRING port ssl { @@ -368,6 +378,7 @@ lookup(char *s) { "home", HOME }, { "include", INCLUDE }, { "interval", INTERVAL }, + { "list", LIST }, { "map", MAP }, { "maps", MAPS }, { "name", NAME }, diff --git a/usr.sbin/ypldap/ypldap.h b/usr.sbin/ypldap/ypldap.h index cc31bd31869..e8d4ac5e060 100644 --- a/usr.sbin/ypldap/ypldap.h +++ b/usr.sbin/ypldap/ypldap.h @@ -117,7 +117,9 @@ struct idm { #define F_CONFIGURING 0x00200000 #define F_NEEDAUTH 0x00400000 #define F_FIXED_ATTR(n) (1<<n) +#define F_LIST(n) (1<<n) u_int32_t idm_flags; /* lower 20 reserved */ + u_int32_t idm_list; in_port_t idm_port; char idm_binddn[LINE_WIDTH]; char idm_bindcred[LINE_WIDTH]; @@ -148,7 +150,6 @@ struct idm { #ifdef SSL struct ssl *idm_ssl; #endif - }; struct idm_req { |