/* Copyright (c) 2010, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Dirk Krause nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file useraudi.h Internal definitions for the useraud daemon. */ #ifndef USERAUDI_H_INCLUDED /** Avoid multiple inclusions. */ #define USERAUDI_H_INCLUDED 1 #include #include #include #if DK_HAVE_SYS_TYPES_H #include #endif #if DK_HAVE_SYS_STAT_H #include #endif #if DK_HAVE_SYS_SOCKET_H #include #endif #if DK_HAVE_SYS_UN_H #include #endif #if DK_HAVE_STRING_H #include #endif #if DK_HAVE_CTYPE_H #include #endif #if DK_HAVE_STDLIB_H #include #endif #if DK_HAVE_UNISTD_H #include #endif #if DK_HAVE_SYSLOG_H #include #endif #if DK_HAVE_PWD_H #include #endif #if DK_HAVE_GRP_H #include #endif #if DK_HAVE_SHADOW_H #include #endif #if DK_HAVE_SIGNAL_H #include #endif #if DK_HAVE_STDARG_H #include #endif #if DK_HAVE_TERMIOS_H #include #endif #if DK_HAVE_SYS_TERMIOS_H #include #endif #if DK_HAVE_SYS_TTOLD_H #include #endif #if DK_HAVE_WINCON_H #include #endif #if DK_HAVE_PROCESS_H #include #endif #if DK_HAVE_ERRNO_H #include #endif #if DK_HAVE_SYSLOG #include #endif #if DK_HAVE_GDBM_H #include #endif #if DK_HAVE_NDBM_H #include #endif #if DK_HAVE_DB_H #include #endif #if DK_HAVE_OPENSSL_RAND_H #include #else #error "OpenSSL include file \"openssl/rand.h\" not found!" #endif #if !(DK_HAVE_GDBM_H || DK_HAVE_NDBM_H || DK_HAVE_DB_H) #error "Neither Berkeley DB nor GDBM nor NDBM available!" #endif #if DK_HAVE_CRYPT_H #include #else #error "Include file not found!" #endif #if DK_HAVE_OPENSSL_MD5_H #include #else #error "OpenSSL include file \"openssl/md5.h\" not found!" #endif #if DK_HAVE_OPENSSL_SHA_H #include #else #error "OpenSSL include file \"openssl/sha.h\" not found!" #endif #if DK_HAVE_OPENSSL_RIPEMD_H #include #else #error "OpenSSL include file \"openssl/ripemd.h\" not found!" #endif #include #include #include #include #include #include #include #include #include "useraud.h" /** Abbreviation for a UNIX domain socket address. */ typedef struct sockaddr_un SOUN; /** Size of a UNIX domain socket address. */ #define SZSOUN sizeof(SOUN) /** Abbreviation for an internet domain socket address. */ typedef struct sockaddr_in SOIN; /** Size of an internet domain socket address. */ #define SZSOIN sizeof(SOIN) #ifndef MAXPATHLEN /** Maximum length of file name. */ #define MAXPATHLEN 1024 #endif /** Data for one allowed host address. */ typedef struct { unsigned long ip; /**< IP address. */ unsigned long mask; /**< Net mask. */ } UAPEER; /** Group entry. */ typedef struct { gid_t g; /**< Group ID. */ char *n; /**< Group name. */ } UAG; /** User property. */ typedef struct { int major; /**< Property major number. */ int minor; /**< Property minor number. */ char *value; /**< Property value. */ } UAP; /** Data for one user. */ typedef struct { char *user_name; /**< Login name. */ char *pw_hash; /**< Password hash. */ char *pg_name; /**< Primary group name. */ dk_storage_t *s_g; /**< Collection of groups. */ dk_storage_iterator_t *i_g; /**< Iterator through groups. */ dk_storage_t *s_p; /**< Collection of additional props. */ dk_storage_iterator_t *i_p; /**< Iterator through props. */ char *gecos; /**< User description. */ uid_t uid; /**< User ID. */ gid_t primary_group; /**< Primary group GID. */ int ht; /**< Hash type. */ int st; /**< Hash sub type. */ int sl; /**< Salt length. */ } UAU; /** API for communication between useraud and the backends. */ typedef struct { struct { int c; /**< Command (opcode). */ int f; /**< Additional flags. */ char **t; /**< Array of string pointers. */ char *v; /**< Simple text. */ char *i; /**< IP address used for cookie. */ } a; /**< Arguments. */ struct { unsigned char s; /**< Flag: Success. */ int ec; /**< Error code (if no success). */ UAU *u; /**< User data. */ } r; /**< Results to return. */ } UAB_API; /** Configuration for the useraud daemon. */ typedef struct { char *sockname; /**< Name of socket to listen on. */ char *logname; /**< Name of log file to write. */ char *dbname; /**< Name of database file(s). */ char *seedname; /**< Name of random seed file. */ char *run_as_user; /**< User account to run. */ char *run_as_group; /**< Group to run. */ dk_storage_t *s_be; /**< Backends collection. */ dk_storage_iterator_t *i_be; /**< Iterator through backends. */ dk_storage_t *s_allow; /**< Allowed hosts collection. */ dk_storage_iterator_t *i_allow; /**< Iterator through allowed hosts. */ dk_sdbi_t sdbi; /**< Database. */ unsigned long ttl_challenge; /**< Challenge time to live. */ unsigned long ttl_cookie; /**< Cookie time to live. */ unsigned long ttl_salt; /**< Faked user salt time to live. */ unsigned long sec_cleanup; /**< Cleanup interval in seconds. */ unsigned long to_socket; /**< Socket timeout. */ time_t last_cleanup; /**< Timestamp of last cleanup. */ int ll_file; /**< Log level for file. */ int ll_syslog; /**< Log level for syslog. */ int hash_types; /**< Allowed hash types. */ int sock; /**< Session socket. */ int lgt_cookie; /**< Maximum cookie length. */ int username_test; /**< Flag: Allow user name test. */ unsigned char f_no_such; /**< Flag: Report "no such user". */ } UAC; /** Backend function prototype. */ #if DK_HAVE_PROTOTYPES typedef void ua_be_fct_t(UAC *, /* UAB */ void *, UAB_API *); #else typedef void ua_be_fct_t(); #endif /** Useraud backend. */ typedef struct { dk_storage_t *s_ex; /**< Collection of excluded users. */ dk_storage_iterator_t *i_ex; /**< Iterator trough excl users. */ void *spec; /**< Backend-specific data. */ ua_be_fct_t *f; /**< Backend function. */ unsigned nb; /**< Number of backend. */ int bet; /**< Backend type. */ int ht; /**< Hash type. */ int st; /**< Sub type. */ int sl; /**< Salt length for faked salt. */ dk_storage_t *s_a; /**< Added properties collection. */ dk_storage_iterator_t *i_a; /**< Added properties iterator. */ dk_storage_t *s_m; /**< Mapped properties collection. */ dk_storage_iterator_t *i_m; /**< mapped properties iterator. */ } UAB; /** Hash type. */ typedef struct { int t; /**< Hash type. */ char *n; /**< Name. */ } HT; /** @defgroup backends Backend types. */ /*@{*/ /** No backend defined yet. */ #define USERAUD_BE_UNKNOWN 0 /** System users backend. */ #define USERAUD_BE_SYS 1 /** LDAP backend (not yet implemented). */ #define USERAUD_BE_LDAP 2 /* +++++ Define further backends here. +++++ */ /*@}*/ /** @defgroup hashtypes Hash types. */ /*@{*/ /** No hash type defined yet. */ #define USERAUD_HASH_UNKNOWN 0 /* +++++ Add further hash types here and in uatcs.ctr, ht array. +++++ */ /** Maximum value used for hash types (powers of 2). * When adding further hash types, increase this entry too. * The strongest (most secure) hashing algorithms must have * the largest numbers assigned. */ #define USERAUD_HASH_MAXVAL 128 /** SHA-512. */ #define USERAUD_HASH_SHA512 128 /** SHA-384. */ #define USERAUD_HASH_SHA384 64 /** SHA-256. */ #define USERAUD_HASH_SHA256 32 /** SHA-224. */ #define USERAUD_HASH_SHA224 16 /** RIPE MD 160. */ #define USERAUD_HASH_RIPEMD160 8 /** SHA-1. */ #define USERAUD_HASH_SHA1 4 /** MD5. */ #define USERAUD_HASH_MD5 2 /** Crypt. */ #define USERAUD_HASH_CRYPT 1 /** Crypt subtype DES. */ #define USERAUD_HASHSUB_CRYPT_DES 0 /** Crypt subtype bigcrypt. */ #define USERAUD_HASHSUB_CRYPT_BIG 1 /** Crypt subtype MD5. */ #define USERAUD_HASHSUB_CRYPT_MD5 2 /** Crypt subtype SHA-256. */ #define USERAUD_HASHSUB_CRYPT_SHA256 3 /** Crypt subtype SHA-512. */ #define USERAUD_HASHSUB_CRYPT_SHA512 4 /** Crypt subtype Blowfish (not on all distributions). */ #define USERAUD_HASHSUB_CRYPT_BLOWFISH 5 /*@}*/ #ifdef EXTERN #undef EXTERN #endif #if DK_HAVE_PROTOTYPES #define EXTERN /* nix */ #else #if USERAUD_C #define EXTERN /* nix */ #else #define EXTERN extern #endif #endif #ifdef __cplusplus extern "C" { #endif /** Set exit code for the useraud daemon. * @param i New exit code. */ EXTERN void ua_set_exit_code DK_PR((int i)); /** Check whether we are in debug mode. * @return 1 for debugging, 0 for no debugging. */ EXTERN int ua_get_debug DK_PR((void)); #ifdef __cplusplus }; #endif #ifdef EXTERN #undef EXTERN #endif #if DK_HAVE_PROTOTYPES #define EXTERN /* nix */ #else #if UABESYS_C #define EXTERN /* nix */ #else #define EXTERN extern #endif #endif #ifdef __cplusplus extern "C" { #endif /** System backend function. * @param uac UAC structure. * @param bevp Pointer to backend. * @param a Pointer to API structure. */ EXTERN void uabesys DK_PR((UAC *uac, void *bevp, UAB_API *a)); #ifdef __cplusplus }; #endif #ifdef EXTERN #undef EXTERN #endif #if DK_HAVE_PROTOTYPES #define EXTERN /* nix */ #else #if UACONF_C #define EXTERN /* nix */ #else #define EXTERN extern #endif #endif #ifdef __cplusplus extern "C" { #endif /** Create configuration data structure, read configuration file. * @param fn File name for configuration file. * @param tp Type of program, the useraud daemon uses 1 here. * @return Pointer to new structure on success, NULL on error. */ EXTERN UAC * uac_open DK_PR((char *fn, int tp)); /** Close a configuration data structure, release memory. * @param u Structure to destroy. * */ EXTERN void uac_close DK_PR((UAC *u)); #ifdef __cplusplus }; #endif #ifdef EXTERN #undef EXTERN #endif #if DK_HAVE_PROTOTYPES #define EXTERN /* nix */ #else #if UATCS_C #define EXTERN /* nix */ #else #define EXTERN extern #endif #endif #ifdef __cplusplus extern "C" { #endif /** Get default configuration file name. * @return Default configuration file name. */ EXTERN char * uatcs_get_default_config_file_name DK_PR((void)); /** Get default database name. * @return Default database name. */ EXTERN char * uatcs_get_default_database_name DK_PR((void)); /** Return default socket name. * @return Default socket name. */ EXTERN char * uatcs_get_default_socket_name DK_PR((void)); /** Return default log file name. * @return Default log file name. */ EXTERN char * uatcs_get_default_log_file_name DK_PR((void)); /** Return default random seed file name. * @return Default random seed file name. */ EXTERN char * uatcs_get_default_random_seed DK_PR((void)); /** Convert text containing IP address in dotted decimal notation. * @param hn String containing the IP address * @return IP address in *host* byte order, use htonl() to convert * to network byte order. */ EXTERN unsigned long uatcs_dotted_string_to_ip DK_PR((char *hn)); /** Apply one hashing step. * @param uac UAC structure. * @param d Destination (result) buffer. * @param szd Size of \a d in bytes. * @param s Input for this step (password for the first step). * @param salt Salt for hashing in text form. * @param ht Hash type. * @return 1 on success, 0 on error. */ EXTERN int uatcs_one_hash DK_PR((UAC *uac,char *d,size_t szd,char *s,char *salt,int ht)); /** Correct salt length for crypt() hash salts. * @param uac UAC structure. * @param st Pointer to variable for sub-type. * @param sl Pointer to variable for salt length. * @param hash Password hash as retrieved from backend. */ EXTERN void uatcs_correct_crypt_st_sl DK_PR((UAC *uac, int *st, int *sl, char *hash)); /** Find numeric representation of hash type. * @param n Hash type name. * @return Numeric representation of the hash type on success, 0 on error. */ EXTERN int uatcs_hash_type DK_PR((char *n)); /** Return or-combination of all hash types listed in \a n. * @param n Hash type names. * @return Or-combination of all hash types listed in \a n. */ EXTERN int uatcs_all_hash_types DK_PR((char *n)); /** Create salt for one hashing step. * @param uac UAC structure. * @param d Destination buffer. * @param szd Size of \a d in bytes. * @param ht Hash type. * @param st Hash sub-type, only used for crypt() hashes. */ EXTERN int uatcs_create_salt DK_PR((UAC *uac, char *d, size_t szd, int ht, int st)); /** Get text representation of a hash type. * @param t Numeric representation of hash type. * @return Name of hash type on success, NULL on error. */ EXTERN char * uatcs_get_hash_name DK_PR((int t)); /** Get alpha-numeric character. * @param i Index. * @return One character. */ EXTERN char uatcs_get_alnum DK_PR((unsigned i)); /** Apply a challenge on a password to create the response. * @param uac UAC structure. * @param ct Challenge type (list of hash methods and salt lengths). * @param ch Challenge (the salts for the hashing steps). * @param pw Password to hash. * @param o Output buffer. * @param szo Size of \a o in bytes. * @param rf Flag: Do (1) or skip (0) the first hash step. * @return 1 on success, 0 on error. */ EXTERN int uatcs_apply_challenge DK_PR((UAC *uac, char *ct, char *ch, char *pw, char *o, size_t szo, int rf)); #ifdef __cplusplus }; #endif #ifdef EXTERN #undef EXTERN #endif #if DK_HAVE_PROTOTYPES #define EXTERN /* nix */ #else #if UAB_C #define EXTERN /* nix */ #else #define EXTERN extern #endif #endif #ifdef __cplusplus extern "C" { #endif /** Compare two lognames (used to build the sorted collection of * excluded users). * @param l Left name. * @param r Right name. * @param cr Comparison criteria (ignored). * @return Comparison result. */ EXTERN int uab_compare_lognames DK_PR((void *l, void *r, int cr)); /** Create new backend structure. * @param uac UAC structure. * @param n Index of the backend. * @param t Backend type. * @param f Backend function. * @param fn File name of configuration file. * @param lineno Line number in configuration file. */ EXTERN UAB * uab_new DK_PR((UAC *uac, unsigned n, int t, ua_be_fct_t *f, char *fn, unsigned long lineno)); /** Delete a backend structure. * @param uac UAC structure. * @param u Backend structure to delete. */ EXTERN void uab_delete DK_PR((UAC *uac, UAB *u)); #ifdef __cplusplus }; #endif #ifdef EXTERN #undef EXTERN #endif #if DK_HAVE_PROTOTYPES #define EXTERN /* nix */ #else #if UALOG_C #define EXTERN /* nix */ #else #define EXTERN extern #endif #endif #ifdef __cplusplus extern "C" { #endif /** Set debug mode. * @param f Flag: Debug mode on (1) or off (0). */ EXTERN void ualog_set_debug DK_PR((int f)); /** Write log message. * @param u UAC structure. * @param ll Log level (DK_LOG_LEVEL_xxx). * @param msg Array of texts to write. * @param n Number of texts in the array. */ EXTERN void ualog DK_PR((UAC *u, int ll, char **msg, int n)); /** Log a simple message. * @param u UAC structure. * @param ll Log level. * @param i Index of message in the kw array in ualog.c. */ EXTERN void ualog_1 DK_PR((UAC *u, int ll, size_t i)); /** Log a combined message consisting of a message start, * an additional text and a message end. * @param u UAC structure. * @param ll Log level. * @param i1 Index of the message start in the kw array. * @param i2 Index of the message end in the kw array. * @param s Text between start and end (for example a file name). */ EXTERN void ualog_3 DK_PR((UAC *u, int ll, size_t i1, size_t i2, char *s)); /** Write a simple log message with file name and line number. * This is used when processing the configuration file. * @param u UAC structure. * @param ll Log level. * @param fn File name to use for error position. * @param l Line number to use for error position. * @param i Index of message in th kw array. */ EXTERN void ualog_file_lineno_1 DK_PR((UAC *u,int ll,char *fn,unsigned long l,size_t i)); #ifdef __cplusplus }; #endif #ifdef EXTERN #undef EXTERN #endif #if DK_HAVE_PROTOTYPES #define EXTERN /* nix */ #else #if UATOOL_C #define EXTERN /* nix */ #else #define EXTERN extern #endif #endif #ifdef __cplusplus extern "C" { #endif /** Get modification time of a file. This is used to compare the last * modification time of the configuration file against the * time of the last configuration-read. * @param fn File name. * @return Mofification timestamp. */ EXTERN time_t uat_modtime DK_PR((char *fn)); /** Get a user password entry. * @param n User name. * @return Password struct on success, NULL on error. */ EXTERN struct passwd * uat_getpwnam DK_PR((char *n)); /** Get a user shadow entry. * @param n User name. * @return Shadow struct on success, NULL on error. */ EXTERN struct spwd * uat_getspnam DK_PR((char *n)); /** Get a group entry. * @param gn Group name. * @return Group entry on success, NULL on error. */ EXTERN struct group * uat_getgrnam DK_PR((char *gn)); /** Save PRNG seed to file. * @param uac UAC structure. */ EXTERN void uat_save_seed DK_PR((UAC *uac)); /** Attempt to seed PRNG. * We try to seed the PRNG from different sources: a file name specified * in the configuration file, a file specified in the "RANDFILE" * environment variable, /dev/urandom, /dev/random, and EGD socket * specified in the "EGDSOCKET" environment variable and the default * EGD socket file name /var/run/egd-pool. * @param uac UAC structure. * @return 1 on success, 0 on error. */ EXTERN int uat_get_seed DK_PR((UAC *uac)); /** Create parent directories for a file and set ownership and group. * @param uac UAC structure. * @param fn File name to create parents for. * @param nu User ID to use for new directories. * @param ng Group ID to use for new directories. * @return 1 on success, 0 on error. */ EXTERN int uat_create_parent DK_PR((UAC *uac, char *fn, uid_t nu, gid_t ng)); #ifdef __cplusplus }; #endif #ifdef EXTERN #undef EXTERN #endif #if DK_HAVE_PROTOTYPES #define EXTERN /* nix */ #else #if UABAPI_C #define EXTERN /* nix */ #else #define EXTERN extern #endif #endif #ifdef __cplusplus extern "C" { #endif /** Initialize UAB_API structure. * @param a Structure to initialize. */ EXTERN void uabapi_init DK_PR((UAB_API *a)); #ifdef __cplusplus }; #endif #ifdef EXTERN #undef EXTERN #endif #if DK_HAVE_PROTOTYPES #define EXTERN /* nix */ #else #if UAU_C #define EXTERN /* nix */ #else #define EXTERN extern #endif #endif #ifdef __cplusplus extern "C" { #endif /** Create user structure, initialize it. * The structure is created in dynamically allocated memory, * use uau_delete() to release the memory. * @param n User name. * @return Pointer to new structure on success, NULL on error. */ EXTERN UAU * uau_new DK_PR((char *n)); /** Release memory used for a user structure. * @param u User structure to destroy. */ EXTERN void uau_delete DK_PR((UAU *u)); /** Create a group structure. * The structure is created in dynamically allocated memory, use * uau_group_delete() to destroy the structure and release the memory. * @param name Group name. * @param gid Group ID. * @return Pointer to the new structure on success, NULL on error. */ EXTERN UAG * uau_group_new DK_PR((char *name, gid_t gid)); /** Destory group structure and release memory. * @param g Structure to destroy. */ EXTERN void uau_group_delete DK_PR((UAG *g)); /** Create property structure. * The structure is created in dynamically allocated memory, use * uau_property_delete() do destroy the structure and release the * memory. * @param maj Major property number. * @param min Minor property number. * @param v Text value. * @return Pointer to the new structure on success, NULL on error. */ EXTERN UAP * uau_property_new DK_PR((int maj, int min, char *v)); /** Destroy property structure, release memory. * @param uap Property structure to destroy. */ EXTERN void uau_property_delete DK_PR((UAP *uap)); #ifdef __cplusplus }; #endif #ifdef EXTERN #undef EXTERN #endif #if DK_HAVE_PROTOTYPES #define EXTERN /* nix */ #else #if USERAUD_C #define EXTERN /* nix */ #else #define EXTERN extern #endif #endif #ifdef __cplusplus extern "C" { #endif /** Check whether we can continue in the outer loop. * If there was a signal, we should not execute actions taking * a longer time. * @return Flag: Can continue. */ EXTERN int useraud_get_outer_loop DK_PR((void)); #ifdef __cplusplus }; #endif #endif /* USERAUD_H_INCLUDED */