[BACK]Return to ldapd.h CVS log [TXT][DIR] Up to [local] / src / usr.sbin / ldapd

File: [local] / src / usr.sbin / ldapd / ldapd.h (download)

Revision 1.36, Wed Dec 15 04:00:15 2021 UTC (2 years, 5 months ago) by deraadt
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1
Changes since 1.35: +2 -2 lines

PATH_MAX+1 rarely makes sense, and abort if this happens in the imsg.
ok jmatthew millert

/*	$OpenBSD: ldapd.h,v 1.36 2021/12/15 04:00:15 deraadt Exp $ */

/*
 * Copyright (c) 2009, 2010 Martin Hedenfalk <martin@bzero.se>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef _LDAPD_H
#define _LDAPD_H

#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/tree.h>
#include <sys/types.h>
#include <sys/uio.h>

#include <event.h>
#include <imsg.h>
#include <limits.h>
#include <pwd.h>
#include <stdarg.h>
#include <tls.h>

#include "aldap.h"
#include "schema.h"
#include "btree.h"
#include "imsgev.h"
#include "evbuffer_tls.h"

#define CONFFILE		 "/etc/ldapd.conf"
#define LDAPD_USER		 "_ldapd"
#define LDAPD_SOCKET		 "/var/run/ldapd.sock"
#define DATADIR			 "/var/db/ldap"
#define LDAP_PORT		 389
#define LDAPS_PORT		 636
#define LDAPD_SESSION_TIMEOUT	 30
#define FD_RESERVE		 8 /* 5 overhead, 2 for db, 1 accept */

#define F_STARTTLS		 0x01
#define F_LDAPS			 0x02
#define F_SSL			(F_LDAPS|F_STARTTLS)

#define F_SECURE		 0x04
#define F_LEGACY		 0x08

#define F_SCERT			 0x01

struct conn;

struct aci {
	SIMPLEQ_ENTRY(aci)	 entry;
#define ACI_DENY		 0
#define ACI_ALLOW		 1
	int			 type;
#define ACI_READ		 0x01
#define ACI_WRITE		 0x02
#define ACI_COMPARE		 0x04
#define ACI_CREATE		 0x08
#define ACI_BIND		 0x10
#define ACI_ALL			 0x1F
	int			 rights;
	enum scope		 scope;		/* base, onelevel or subtree */
	char			*attribute;
	char			*target;
	char			*subject;
	char			*filter;
};
SIMPLEQ_HEAD(acl, aci);

/* An LDAP request.
 */
struct request {
	TAILQ_ENTRY(request)	 next;
	unsigned int		 type;
	long long		 msgid;
	struct ber_element	*root;
	struct ber_element	*op;
	struct conn		*conn;
	int			 replayed;	/* true if replayed request */
};
TAILQ_HEAD(request_queue, request);

enum index_type {
	INDEX_NONE,
	INDEX_EQUAL	= 1,
	INDEX_APPROX	= 1,
	INDEX_PRESENCE	= 1,
	INDEX_SUBSTR
};

struct attr_index {
	TAILQ_ENTRY(attr_index)	 next;
	char			*attr;
	enum index_type		 type;
};
TAILQ_HEAD(attr_index_list, attr_index);

struct referral {
	SLIST_ENTRY(referral)	 next;
	char			*url;
};
SLIST_HEAD(referrals, referral);

struct namespace {
	TAILQ_ENTRY(namespace)	 next;
	char			*suffix;
	struct referrals	 referrals;
	char			*rootdn;
	char			*rootpw;
	char			*data_path;
	char			*indx_path;
	struct btree		*data_db;
	struct btree		*indx_db;
	struct btree_txn	*data_txn;
	struct btree_txn	*indx_txn;
	int			 sync;		/* 1 = fsync after commit */
	struct attr_index_list	 indices;
	unsigned int		 cache_size;
	unsigned int		 index_cache_size;
	struct request_queue	 request_queue;
	struct event		 ev_queue;
	unsigned int		 queued_requests;
	struct acl		 acl;
	int			 relax;		/* relax schema validation */
	int			 compression_level;	/* 0-9, 0 = disabled */
};

TAILQ_HEAD(namespace_list, namespace);

struct index
{
	TAILQ_ENTRY(index)	 next;
	char			*prefix;
};

/* A query plan.
 */
struct plan
{
	TAILQ_ENTRY(plan)	 next;
	TAILQ_HEAD(, plan)	 args;
	TAILQ_HEAD(, index)	 indices;
	struct attr_type	*at;
	char			*adesc;
	union {
		char			*value;
		struct ber_element	*substring;
	} assert;
	int			 op;
	int			 indexed;
	int			 undefined;
};

/* For OR filters using multiple indices, matches are not unique. Remember
 * all DNs sent to the client to make them unique.
 */
struct uniqdn {
	RB_ENTRY(uniqdn)	 link;
	struct btval		 key;
};
RB_HEAD(dn_tree, uniqdn);
RB_PROTOTYPE(dn_tree, uniqdn, link, uniqdn_cmp);

/* An LDAP search request.
 */
struct search {
	TAILQ_ENTRY(search)	 next;
	int			 init;		/* 1 if cursor initiated */
	struct conn		*conn;
	struct request		*req;
	struct namespace	*ns;
	struct btree_txn	*data_txn;
	struct btree_txn	*indx_txn;
	struct cursor		*cursor;
	unsigned int		 nscanned, nmatched, ndups;
	time_t			 started_at;
	long long		 szlim, tmlim;	/* size and time limits */
	int			 typesonly;	/* not implemented */
	long long		 scope;
	long long		 deref;		/* not implemented */
	char			*basedn;
	struct ber_element	*filter, *attrlist;
	struct plan		*plan;
	struct index		*cindx;		/* current index */
	struct dn_tree		 uniqdns;
};

struct listener {
	unsigned int		 flags;		/* F_STARTTLS or F_LDAPS */
	struct sockaddr_storage	 ss;
	int			 port;
	int			 fd;
	struct event		 ev;
	struct event		 evt;
	char			 ssl_cert_name[PATH_MAX];
	struct ssl		*ssl;
	struct tls		*tls;
	TAILQ_ENTRY(listener)	 entry;
};
TAILQ_HEAD(listenerlist, listener);

/* An LDAP client connection.
 */
struct conn {
	TAILQ_ENTRY(conn)	 next;
	int			 fd;
	struct bufferevent	*bev;
	struct ber		 ber;
	int			 disconnect;
	struct request		*bind_req;	/* ongoing bind request */
	char			*binddn;
	char			*pending_binddn;
	TAILQ_HEAD(, search)	 searches;
	struct listener		*listener;	/* where it connected from */

	/* SSL support */
	struct tls		*tls;
	struct buffertls	 buftls;
	unsigned int		 s_flags;
};
TAILQ_HEAD(conn_list, conn);

struct ssl {
	SPLAY_ENTRY(ssl)	 ssl_nodes;
	char			 ssl_name[PATH_MAX];
	uint8_t			*ssl_cert;
	size_t			 ssl_cert_len;
	uint8_t			*ssl_key;
	size_t			 ssl_key_len;
	uint8_t			 flags;
	struct tls_config	*config;
};

struct ldapd_config
{
	struct namespace_list		 namespaces;
	struct listenerlist		 listeners;
	SPLAY_HEAD(ssltree, ssl)	*sc_ssl;
	struct referrals		 referrals;
	struct acl			 acl;
	struct schema			*schema;
	char				*rootdn;
	char				*rootpw;
};

struct ldapd_stats
{
	time_t			 started_at;	/* time of daemon startup */
	unsigned long long	 requests;	/* total number of requests */
	unsigned long long	 req_search;	/* search requests */
	unsigned long long	 req_bind;	/* bind requests */
	unsigned long long	 req_mod;	/* add/mod/del requests */
	unsigned long long	 timeouts;	/* search timeouts */
	unsigned long long	 unindexed;	/* unindexed searches */
	unsigned int		 conns;		/* active connections */
	unsigned int		 searches;	/* active searches */
};

struct auth_req
{
	int			 fd;
	long long		 msgid;
	char			 name[128];
	char			 password[128];
};

struct auth_res
{
	int			 ok;
	int			 fd;
	long long		 msgid;
};

struct open_req {
	char			 path[PATH_MAX];
	unsigned int		 rdonly;
};

enum imsg_type {
	IMSG_NONE,
	IMSG_CTL_OK,
	IMSG_CTL_FAIL,
	IMSG_CTL_END,
	IMSG_CTL_STATS,
	IMSG_CTL_NSSTATS,
	IMSG_CTL_LOG_VERBOSE,

	IMSG_LDAPD_AUTH,
	IMSG_LDAPD_AUTH_RESULT,
	IMSG_LDAPD_OPEN,
	IMSG_LDAPD_OPEN_RESULT,
};

struct ns_stat {
	char			 suffix[256];
	struct btree_stat	 data_stat;
	struct btree_stat	 indx_stat;
};

struct ctl_conn {
	TAILQ_ENTRY(ctl_conn)	 entry;
	u_int8_t		 flags;
#define CTL_CONN_NOTIFY		 0x01
#define CTL_CONN_LOCKED		 0x02		/* restricted mode */
	struct imsgev		 iev;
};
TAILQ_HEAD(ctl_connlist, ctl_conn);

struct control_sock {
	const char		*cs_name;
	struct event		 cs_ev;
	struct event		 cs_evt;
	int			 cs_fd;
	int			 cs_restricted;
};

enum ldapd_process {
	PROC_MAIN_AUTH,
	PROC_LDAP_SERVER
};

#define PROC_PARENT_SOCK_FILENO	 3

/* ldapd.c */
extern struct ldapd_stats	 stats;
extern struct ldapd_config	*conf;

void			 imsg_event_add(struct imsgev *iev);
int			 imsg_compose_event(struct imsgev *iev, u_int16_t type,
			    u_int32_t peerid, pid_t pid, int fd, void *data,
			    u_int16_t datalen);
int			 imsg_event_handle(struct imsgev *iev, short event);

/* conn.c */
extern struct conn_list	 conn_list;
struct conn		*conn_by_fd(int fd);
void			 conn_read(struct bufferevent *bev, void *data);
void			 conn_write(struct bufferevent *bev, void *data);
void			 conn_err(struct bufferevent *bev, short w, void *data);
void			 conn_accept(int fd, short why, void *data);
void			 conn_close(struct conn *conn);
int			 conn_close_any(void);
void			 conn_disconnect(struct conn *conn);
void			 request_dispatch(struct request *req);
void			 request_free(struct request *req);

/* ldape.c */
void			 ldape(int, int, char *);
int			 ldap_abandon(struct request *req);
int			 ldap_unbind(struct request *req);
int			 ldap_compare(struct request *req);
int			 ldap_extended(struct request *req);

void			 send_ldap_result(struct conn *conn, int msgid,
				unsigned int type, long long result_code);
int			 ldap_respond(struct request *req, int code);
int			 ldap_refer(struct request *req, const char *basedn,
			     struct search *search, struct referrals *refs);

/* namespace.c
 */
struct namespace	*namespace_new(const char *suffix);
int			 namespace_open(struct namespace *ns);
int			 namespace_reopen_data(struct namespace *ns);
int			 namespace_reopen_indx(struct namespace *ns);
int			 namespace_set_data_fd(struct namespace *ns, int fd);
int			 namespace_set_indx_fd(struct namespace *ns, int fd);
struct namespace	*namespace_init(const char *suffix, const char *dir);
void			 namespace_close(struct namespace *ns);
void			 namespace_remove(struct namespace *ns);
struct ber_element	*namespace_get(struct namespace *ns, char *dn);
int			 namespace_exists(struct namespace *ns, char *dn);
int			 namespace_add(struct namespace *ns, char *dn,
				struct ber_element *root);
int			 namespace_update(struct namespace *ns, char *dn,
				struct ber_element *root);
int			 namespace_del(struct namespace *ns, char *dn);
struct namespace	*namespace_lookup_base(const char *basedn,
				int include_referrals);
struct namespace	*namespace_for_base(const char *basedn);
int			 namespace_has_referrals(struct namespace *ns);
struct referrals	*namespace_referrals(const char *basedn);
int			 namespace_has_index(struct namespace *ns,
				const char *attr, enum index_type type);
int			 namespace_begin_txn(struct namespace *ns,
				struct btree_txn **data_txn,
				struct btree_txn **indx_txn, int rdonly);
int			 namespace_begin(struct namespace *ns);
int			 namespace_commit(struct namespace *ns);
void			 namespace_abort(struct namespace *ns);
int			 namespace_queue_request(struct namespace *ns,
				struct request *req);
void			 namespace_queue_schedule(struct namespace *ns,
				unsigned int usec);
void			 namespace_cancel_conn(struct conn *conn);
int			 namespace_conn_queue_count(struct conn *conn);

int			 namespace_ber2db(struct namespace *ns,
				struct ber_element *root, struct btval *val);
struct ber_element	*namespace_db2ber(struct namespace *ns,
				struct btval *val);

/* attributes.c */
struct ber_element	*ldap_get_attribute(struct ber_element *root,
				const char *attr);
struct ber_element	*ldap_find_attribute(struct ber_element *entry,
				struct attr_type *at);
struct ber_element	*ldap_find_value(struct ber_element *elm,
				const char *value);
struct ber_element	*ldap_add_attribute(struct ber_element *root,
				const char *attr, struct ber_element *vals);
int			 ldap_set_values(struct ber_element *elm,
				struct ber_element *vals);
int			 ldap_merge_values(struct ber_element *elm,
				struct ber_element *vals);
int			 ldap_del_attribute(struct ber_element *entry,
				const char *attrdesc);
int			 ldap_del_values(struct ber_element *elm,
				struct ber_element *vals);
char			*ldap_strftime(time_t tm);
char			*ldap_now(void);

/* control.c */
void			 control_init(struct control_sock *);
void			 control_listen(struct control_sock *);
void			 control_accept(int, short, void *);
void			 control_dispatch_imsg(int, short, void *);
void			 control_cleanup(struct control_sock *);
int			 control_close_any(struct control_sock *);

/* filter.c */
int			 ldap_matches_filter(struct ber_element *root,
				struct plan *plan);

/* search.c */
int			 ldap_search(struct request *req);
void			 conn_search(struct search *search);
void			 search_close(struct search *search);
int			 is_child_of(struct btval *key, const char *base);

/* modify.c */
int			 ldap_add(struct request *req);
int			 ldap_delete(struct request *req);
int			 ldap_modify(struct request *req);

/* auth.c */
extern struct imsgev	*iev_ldapd;
int			 ldap_bind(struct request *req);
void			 ldap_bind_continue(struct conn *conn, int ok);
int			 authorized(struct conn *conn, struct namespace *ns,
				int rights, char *dn, char *attr, int scope);

/* parse.y */
int			 parse_config(char *filename);
int			 cmdline_symset(char *s);
int			 ssl_cmp(struct ssl *, struct ssl *);
SPLAY_PROTOTYPE(ssltree, ssl, ssl_nodes, ssl_cmp);


/* logmsg.c */
void			 ldap_loginit(const char *, int, int);
const char		*print_host(struct sockaddr_storage *ss, char *buf,
				size_t len);
void			 hexdump(void *data, size_t len, const char *fmt, ...);
void			 ldap_debug_elements(struct ber_element *root,
			    int context, const char *fmt, ...);
/* util.c */
int			 bsnprintf(char *str, size_t size,
				const char *format, ...);
int			 has_suffix(struct btval *key, const char *suffix);
int			 has_prefix(struct btval *key, const char *prefix);
void			 normalize_dn(char *dn);
int			 ber2db(struct ber_element *root, struct btval *val,
			    int compression_level);
struct ber_element	*db2ber(struct btval *val, int compression_level);
int			 accept_reserve(int sockfd, struct sockaddr *addr,
			    socklen_t *addrlen, int reserve);

/* index.c */
int			 index_entry(struct namespace *ns, struct btval *dn,
				struct ber_element *elm);
int			 unindex_entry(struct namespace *ns, struct btval *dn,
				struct ber_element *elm);
int			 index_to_dn(struct namespace *ns, struct btval *indx,
				struct btval *dn);

/* validate.c */
int	validate_entry(const char *dn, struct ber_element *entry, int relax);

#endif /* _LDAPD_H */