First (incomplete) implementation of Kerberos authentication

SVN revision: 2357
This commit is contained in:
2011-01-17 16:37:43 +00:00
parent 743deb74c8
commit 8d319d9344
4 changed files with 1867 additions and 1265 deletions
+205
View File
@@ -0,0 +1,205 @@
/********************************************************************\
Name: auth.c
Created by: Stefan Ritt
Contents: Authentication subroutines. Currently supported:
- password file authentication
- kerberos5 password authentication
$Id: elog.c 2350 2010-12-23 10:45:10Z ritt $
\********************************************************************/
#include "elogd.h"
#ifdef HAVE_KRB5
#include <krb5/krb5.h>
#endif
extern LOGBOOK *lb_list;
/* ========================================================================== */
/*---- Kerberos5 routines ------------------------------------------*/
#ifdef HAVE_KRB5
int auth_verify_password_krb5(LOGBOOK *lbs, const char *user, const char *password)
{
char *princ_name, str[256], realm[256];
krb5_error_code error;
krb5_principal princ;
krb5_context context;
krb5_creds creds;
krb5_get_init_creds_opt options;
if (krb5_init_context(&context) < 0)
return FALSE;
strlcpy(str, user, sizeof(str));
if (getcfg(lbs->name, "Kerberos Realm", realm, sizeof(realm))) {
strlcat(str, "@", sizeof(str));
strlcat(str, realm, sizeof(str));
}
if ((error = krb5_parse_name(context, str, &princ)) != 0)
return FALSE;
error = krb5_unparse_name(context, princ, &princ_name);
if (is_verbose())
eprintf("Using %s as server principal for authentication\n", princ_name);
memset(&options, 0, sizeof(options));
krb5_get_init_creds_opt_init(&options);
memset(&creds, 0, sizeof(creds));
error = krb5_get_init_creds_password(context, &creds, princ,
(char *)password, NULL,
NULL, 0, NULL, &options);
krb5_free_cred_contents(context, &creds);
krb5_get_init_creds_opt_free(context, &options);
krb5_free_context(context);
if (error)
return FALSE;
return TRUE;
}
int auth_change_password_krb5(LOGBOOK *lbs, const char *user, const char *old_pwd, const char *new_pwd, char *error_str, int error_size)
{
char *princ_name, str[256], realm[256];
int result_code, n;
krb5_error_code error;
krb5_data result_code_string, result_string;
krb5_principal princ;
krb5_context context;
krb5_creds creds;
krb5_get_init_creds_opt options;
if (krb5_init_context(&context) < 0)
return FALSE;
strlcpy(str, user, sizeof(str));
if (getcfg(lbs->name, "Kerberos Realm", realm, sizeof(realm))) {
strlcat(str, "@", sizeof(str));
strlcat(str, realm, sizeof(str));
}
if ((error = krb5_parse_name(context, str, &princ)) != 0)
return FALSE;
error = krb5_unparse_name(context, princ, &princ_name);
if (is_verbose())
eprintf("Using %s as server principal for authentication\n", princ_name);
memset(&options, 0, sizeof(options));
krb5_get_init_creds_opt_init(&options);
krb5_get_init_creds_opt_set_tkt_life(&options, 300);
krb5_get_init_creds_opt_set_forwardable(&options, FALSE);
krb5_get_init_creds_opt_set_proxiable(&options, FALSE);
memset(&creds, 0, sizeof(creds));
error = krb5_get_init_creds_password(context, &creds, princ,
(char *)old_pwd, NULL,
NULL, 0, "kadmin/changepw", &options);
if (error)
return FALSE;
error = krb5_set_password(context, &creds, (char *)new_pwd, princ,
&result_code,
&result_code_string,
&result_string);
if (error)
return FALSE;
error_str[0] = 0;
if (result_code > 0) {
if (result_code_string.length > 0) {
strlcpy(error_str, result_code_string.data, error_size);
if ((int)result_code_string.length < error_size)
error_str[result_code_string.length] = 0;
}
if (result_string.length > 0) {
strlcat(error_str, ": ", error_size);
n = strlen(error_str) + result_string.length;
strlcat(error_str, result_string.data, error_size);
if (n < error_size)
error_str[n] = 0;
}
}
krb5_free_data_contents(context, &result_code_string);
krb5_free_data_contents(context, &result_string);
krb5_free_cred_contents(context, &creds);
krb5_get_init_creds_opt_free(context, &options);
krb5_free_context(context);
if (result_code > 0)
return FALSE;
return TRUE;
}
#endif
/*---- local password file routines --------------------------------*/
int auth_verify_password_file(LOGBOOK *lbs, const char *user, const char *password)
{
char upwd[256], enc_pwd[256];
get_user_line(lbs, (char*)user, upwd, NULL, NULL, NULL, NULL, NULL);
do_crypt(password, enc_pwd, sizeof(enc_pwd));
return strcmp(enc_pwd, upwd) == 0;
}
int auth_change_password_file(LOGBOOK *lbs, const char *user, const char *old_pwd, const char *new_pwd, char *error_str, int error_size)
{
char str[256], file_name[256];
PMXML_NODE node;
if (lbs == NULL)
lbs = &lb_list[0];
if (!lbs->pwd_xml_tree)
return FALSE;
sprintf(str, "/list/user[name=%s]/password", user);
node = mxml_find_node(lbs->pwd_xml_tree, str);
if (node == NULL)
return FALSE;
mxml_replace_node_value(node, new_pwd);
if (get_password_file(lbs, file_name, sizeof(file_name)))
mxml_write_tree(file_name, lbs->pwd_xml_tree);
return TRUE;
}
/*---- common function entry points --------------------------------*/
int auth_verify_password(LOGBOOK *lbs, const char *user, const char *password)
{
char str[256];
getcfg(lbs->name, "Authentication", str, sizeof(str));
if (stricmp(str, "Kerberos Password") == 0)
return auth_verify_password_krb5(lbs, user, password);
return auth_verify_password_file(lbs, user, password);
}
int auth_change_password(LOGBOOK *lbs, const char *user, const char *old_pwd, const char *new_pwd, char *error_str, int error_size)
{
char str[256];
getcfg(lbs->name, "Authentication", str, sizeof(str));
if (stricmp(str, "Kerberos Password") == 0)
return auth_change_password_krb5(lbs, user, old_pwd, new_pwd, error_str, error_size);
return auth_change_password_file(lbs, user, old_pwd, new_pwd, error_str, error_size);
}
+190 -58
View File
@@ -186,13 +186,6 @@ size_t strlcat(char *dst, const char *src, size_t size)
#endif // STRLCPY_DEFINED
char *sha256_crypt(const char *key, const char *salt);
void do_crypt(char *s, char *d, int size)
{
strlcpy(d, sha256_crypt(s, "$5$") + 4, size);
}
/*-------------------------------------------------------------------*/
void stou(char *str)
@@ -364,9 +357,8 @@ int ssl_connect(int sock, SSL ** ssl_con)
char request[100000], response[100000], *content;
INT retrieve_elog(char *host, int port, char *subdir, int ssl, char *experiment,
char *passwd, char *uname, char *upwd, int message_id,
char attrib_name[MAX_N_ATTR][NAME_LENGTH], char attrib[MAX_N_ATTR][NAME_LENGTH], char *text)
INT retrieve_sid(char *host, int port, char *subdir, int ssl, char *experiment,
char *uname, char *upwd, char *sid)
/********************************************************************\
Routine: retrive_elog
@@ -378,9 +370,174 @@ INT retrieve_elog(char *host, int port, char *subdir, int ssl, char *experiment,
int port ELog server port number
char *subdir Subdirectoy to elog server
int ssl Flag for using SSL layer
char *passwd Write password
char *uname User name
char *upwd User password
Output:
char *sid Session ID
Function value:
EL_SUCCESS Successful completion
\********************************************************************/
{
int i, n, first, sock;
char str[256];
#ifdef HAVE_SSL
SSL *ssl_con;
#endif
if (ssl) /* avoid compiler warning */
sock = 0;
sock = elog_connect(host, port);
if (sock < 0)
return sock;
#ifdef HAVE_SSL
if (ssl)
if (ssl_connect(sock, &ssl_con) < 0) {
printf("elogd server does not run SSL protocol\n");
return -1;
}
#endif
/* compose request */
strcpy(request, "GET /");
strlcpy(str, experiment, sizeof(str));
url_encode(str, sizeof(str));
if (subdir[0] && experiment[0])
sprintf(request + strlen(request), "%s/%s/", subdir, str);
else if (subdir[0])
sprintf(request + strlen(request), "%s/", subdir);
else if (experiment[0])
sprintf(request + strlen(request), "%s/", str);
strcat(request, " HTTP/1.0\r\n");
sprintf(request + strlen(request), "User-Agent: ELOG\r\n");
first = 1;
if (uname[0]) {
if (first)
sprintf(request + strlen(request), "Cookie: ");
first = 0;
sprintf(request + strlen(request), "uname=%s;", uname);
}
if (upwd[0]) {
if (first)
sprintf(request + strlen(request), "Cookie: ");
first = 0;
sprintf(request + strlen(request), "upassword=%s;", upwd);
}
/* finish cookie line */
if (!first)
strcat(request, "\r\n");
strcat(request, "\r\n");
/* send request */
#ifdef HAVE_SSL
if (ssl)
SSL_write(ssl_con, request, strlen(request));
else
#endif
send(sock, request, strlen(request), 0);
if (verbose) {
printf("Request sent to host:\n");
puts(request);
}
/* receive response */
memset(response, 0, sizeof(response));
#ifdef HAVE_SSL
if (ssl)
i = SSL_read(ssl_con, response, sizeof(response) - 1);
else
#endif
i = recv(sock, response, sizeof(response) - 1, 0);
if (i < 0) {
perror("Cannot receive response");
return -1;
}
n = i;
while (i > 0) {
#ifdef HAVE_SSL
if (ssl)
i = SSL_read(ssl_con, response + n, sizeof(response) - 1 - n);
else
#endif
i = recv(sock, response + n, sizeof(response) - 1 - n, 0);
if (i > 0)
n += i;
}
response[n] = 0;
#ifdef HAVE_SSL
if (ssl) {
SSL_shutdown(ssl_con);
SSL_free(ssl_con);
}
#endif
closesocket(sock);
if (verbose) {
printf("Response received:\n");
puts(response);
}
/* check response status */
if (strstr(response, "302 Found")) {
if (strstr(response, "Location:")) {
if (strstr(response, "fail"))
printf("Error: Invalid user name or password\n");
else {
if (strstr(response, "sid")) {
strlcpy(str, strstr(response, "sid")+4, sizeof(str));
if (strchr(str, ';'))
*strchr(str, ';') = 0;
strcpy(sid, str);
return 1;
}
}
}
} else if (strstr(response, "Logbook Selection"))
printf("Error: No logbook specified\n");
else if (strstr(response, "enter password"))
printf("Error: Missing or invalid password\n");
else if (strstr(response, "form name=form1"))
printf("Error: Missing or invalid user name/password\n");
else
printf("Error transmitting message\n");
return 0;
}
/*------------------------------------------------------------------*/
char request[100000], response[100000], *content;
INT retrieve_elog(char *host, int port, char *subdir, int ssl, char *experiment,
char *sid, int message_id, char attrib_name[MAX_N_ATTR][NAME_LENGTH],
char attrib[MAX_N_ATTR][NAME_LENGTH], char *text)
/********************************************************************\
Routine: retrive_elog
Purpose: Retrive an ELog entry for edit/reply
Input:
char *host Host name where ELog server runs
int port ELog server port number
char *subdir Subdirectoy to elog server
int ssl Flag for using SSL layer
char *sid Session ID
int message_id Message to retrieve
char *attrib_name Attribute names
char *attrib Attribute values
@@ -392,7 +549,7 @@ INT retrieve_elog(char *host, int port, char *subdir, int ssl, char *experiment,
\********************************************************************/
{
int i, n, first, index, sock;
char str[256], encrypted_passwd[256], *ph, *ps;
char str[256], *ph, *ps;
#ifdef HAVE_SSL
SSL *ssl_con;
#endif
@@ -427,30 +584,13 @@ INT retrieve_elog(char *host, int port, char *subdir, int ssl, char *experiment,
sprintf(request + strlen(request), "User-Agent: ELOG\r\n");
first = 1;
if (passwd[0]) {
if (sid[0]) {
if (first)
sprintf(request + strlen(request), "Cookie: ");
first = 0;
do_crypt(passwd, encrypted_passwd, sizeof(encrypted_passwd));
sprintf(request + strlen(request), "wpwd=%s;", encrypted_passwd);
}
if (uname[0]) {
if (first)
sprintf(request + strlen(request), "Cookie: ");
first = 0;
sprintf(request + strlen(request), "unm=%s;", uname);
}
if (upwd[0]) {
if (first)
sprintf(request + strlen(request), "Cookie: ");
first = 0;
do_crypt(upwd, encrypted_passwd, sizeof(encrypted_passwd));
sprintf(request + strlen(request), "upwd=%s;", encrypted_passwd);
sprintf(request + strlen(request), "sid=%s;", sid);
}
/* finish cookie line */
@@ -594,7 +734,6 @@ INT retrieve_elog(char *host, int port, char *subdir, int ssl, char *experiment,
/*------------------------------------------------------------------*/
INT submit_elog(char *host, int port, int ssl, char *subdir, char *experiment,
char *passwd,
char *uname, char *upwd,
int reply,
int quote_on_reply,
@@ -617,7 +756,6 @@ INT submit_elog(char *host, int port, int ssl, char *subdir, char *experiment,
in port ELog server port number
int ssl SSL flag
char *subdir Subdirectoy to elog server
char *passwd Write password
char *uname User name
char *upwd User password
int reply Reply to existing message
@@ -638,7 +776,7 @@ INT submit_elog(char *host, int port, int ssl, char *subdir, char *experiment,
\********************************************************************/
{
int status, sock, i, n, header_length, content_length, index;
char host_name[256], boundary[80], str[80], encrypted_passwd[256], *p, *old_encoding;
char host_name[256], boundary[80], str[80], *p, *old_encoding, sid[32];
char old_attrib_name[MAX_N_ATTR][NAME_LENGTH], old_attrib[MAX_N_ATTR][NAME_LENGTH];
struct hostent *phe;
#ifdef HAVE_SSL
@@ -663,9 +801,16 @@ INT submit_elog(char *host, int port, int ssl, char *subdir, char *experiment,
if (strchr(host_name, '.') == NULL)
strcpy(host_name, phe->h_name);
/* first retrieve our session ID */
status = retrieve_sid(host, port, subdir, ssl, experiment,
uname, upwd, sid);
if (status != 1)
return status;
if (edit) {
status =
retrieve_elog(host, port, subdir, ssl, experiment, passwd, uname, upwd, edit,
retrieve_elog(host, port, subdir, ssl, experiment, sid, edit,
old_attrib_name, old_attrib, old_text);
if (status != 1)
@@ -695,7 +840,7 @@ INT submit_elog(char *host, int port, int ssl, char *subdir, char *experiment,
if (reply) {
status =
retrieve_elog(host, port, subdir, ssl, experiment, passwd, uname, upwd, reply,
retrieve_elog(host, port, subdir, ssl, experiment, sid, reply,
old_attrib_name, old_attrib, old_text);
if (status != 1)
@@ -806,15 +951,11 @@ INT submit_elog(char *host, int port, int ssl, char *subdir, char *experiment,
strcpy(content, boundary);
strcat(content, "\r\nContent-Disposition: form-data; name=\"cmd\"\r\n\r\nSubmit\r\n");
if (uname[0])
if (sid[0]) {
sprintf(content + strlen(content),
"%s\r\nContent-Disposition: form-data; name=\"unm\"\r\n\r\n%s\r\n", boundary, uname);
if (upwd[0]) {
do_crypt(upwd, encrypted_passwd, sizeof(encrypted_passwd));
"%s\r\nContent-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n", boundary, sid);
sprintf(content + strlen(content),
"%s\r\nContent-Disposition: form-data; name=\"upwd\"\r\n\r\n%s\r\n", boundary,
encrypted_passwd);
"%s\r\nContent-Disposition: form-data; name=\"sidclose\"\r\n\r\n1\r\n", boundary);
}
if (experiment[0])
@@ -895,11 +1036,6 @@ INT submit_elog(char *host, int port, int ssl, char *subdir, char *experiment,
sprintf(request + strlen(request), "User-Agent: ELOG\r\n");
sprintf(request + strlen(request), "Content-Length: %d\r\n", content_length);
if (passwd[0]) {
do_crypt(passwd, encrypted_passwd, sizeof(encrypted_passwd));
sprintf(request + strlen(request), "Cookie: wpwd=%s\r\n", encrypted_passwd);
}
strcat(request, "\r\n");
header_length = strlen(request);
@@ -1030,14 +1166,14 @@ INT submit_elog(char *host, int port, int ssl, char *subdir, char *experiment,
int main(int argc, char *argv[])
{
char str[1000], uname[80], upwd[80];
char host_name[256], logbook[32], textfile[256], password[80], subdir[256];
char host_name[256], logbook[32], textfile[256], subdir[256];
char *buffer[MAX_ATTACHMENTS], attachment[MAX_ATTACHMENTS][256];
INT att_size[MAX_ATTACHMENTS];
INT i, n, fh, n_att, n_attr, port, reply, quote_on_reply, edit, encoding, suppress, size, ssl;
char attr_name[MAX_N_ATTR][NAME_LENGTH], attrib[MAX_N_ATTR][NAME_LENGTH];
text[0] = textfile[0] = uname[0] = upwd[0] = suppress = quote_on_reply = 0;
host_name[0] = logbook[0] = password[0] = subdir[0] = 0;
host_name[0] = logbook[0] = subdir[0] = 0;
n_att = n_attr = reply = edit = encoding = 0;
port = 80;
ssl = 0;
@@ -1068,8 +1204,6 @@ int main(int argc, char *argv[])
port = atoi(argv[++i]);
else if (argv[i][1] == 'l')
strcpy(logbook, argv[++i]);
else if (argv[i][1] == 'w')
strcpy(password, argv[++i]);
else if (argv[i][1] == 'd')
strcpy(subdir, argv[++i]);
else if (argv[i][1] == 'u') {
@@ -1109,8 +1243,7 @@ int main(int argc, char *argv[])
printf(" -l logbook/experiment Name of logbook or experiment\n");
printf(" -s Use SSL for communication\n");
printf(" [-v] For verbose output\n");
printf(" [-w password] Write password defined on server\n");
printf(" [-u username password] Wser name and password\n");
printf(" [-u username password] User name and password\n");
printf(" [-f <attachment>] (up to %d attachments)\n", MAX_ATTACHMENTS);
printf(" -a <attribute>=<value> (up to %d attributes)\n", MAX_N_ATTR);
printf(" [-r <id>] Reply to existing message\n");
@@ -1238,9 +1371,8 @@ int main(int argc, char *argv[])
}
/* now submit message */
submit_elog(host_name, port, ssl, subdir, logbook, password,
uname, upwd, reply, quote_on_reply, edit, suppress, encoding, attr_name, attrib, n_attr, text,
attachment, buffer, att_size);
submit_elog(host_name, port, ssl, subdir, logbook, uname, upwd, reply, quote_on_reply,
edit, suppress, encoding, attr_name, attrib, n_attr, text, attachment, buffer, att_size);
for (i = 0; i < MAX_ATTACHMENTS; i++)
if (buffer[i])
+1160 -1207
View File
File diff suppressed because it is too large Load Diff
+312
View File
@@ -0,0 +1,312 @@
/********************************************************************
Name: elogd.h
Created by: Stefan Ritt
Contents: Header file for ELOG program
$Id: elogd.c 2354 2011-01-10 11:53:11Z ritt $
\********************************************************************/
/* Version of ELOG */
#define VERSION "2.8.1"
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <assert.h>
#include <locale.h>
/* Default name of the configuration file. */
#ifndef CFGFILE
#define CFGFILE "elogd.cfg"
#endif
/* Default TCP port for server. */
#ifndef DEFAULT_PORT
#define DEFAULT_PORT 80
#endif
#ifdef _MSC_VER
#define OS_WINNT
#define DIR_SEPARATOR '\\'
#define DIR_SEPARATOR_STR "\\"
#define snprintf _snprintf
#include <windows.h>
#include <io.h>
#include <conio.h>
#include <time.h>
#include <direct.h>
#include <sys/stat.h>
#else
#define OS_UNIX
#ifdef __APPLE__
#define OS_MACOSX
#endif
#define TRUE 1
#define FALSE 0
#ifndef O_TEXT
#define O_TEXT 0
#define O_BINARY 0
#endif
#define DIR_SEPARATOR '/'
#define DIR_SEPARATOR_STR "/"
#ifndef DEFAULT_USER
#define DEFAULT_USER "nobody"
#endif
#ifndef DEFAULT_GROUP
#define DEFAULT_GROUP "nogroup"
#endif
#ifndef PIDFILE
#define PIDFILE "/var/run/elogd.pid"
#endif
typedef int BOOL;
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <dirent.h>
#include <errno.h>
#include <ctype.h>
#include <pwd.h>
#include <grp.h>
#include <syslog.h>
#include <termios.h>
#define closesocket(s) close(s)
#ifndef stricmp
#define stricmp(s1, s2) strcasecmp(s1, s2)
#endif
gid_t orig_gid; /* Original effective GID before dropping privilege */
uid_t orig_uid; /* Original effective UID before dropping privilege */
char pidfile[256]; /* Pidfile name */
#endif /* OS_UNIX */
#ifdef __CYGWIN__ /* bug in cygwin, 'tmezone' not linked automatically */
long _timezone;
#endif
/* SSL includes */
#ifdef HAVE_SSL
#include <openssl/ssl.h>
#endif
/* local includes */
#include "regex.h"
#include "mxml.h"
#include "strlcpy.h"
#define SYSLOG_PRIORITY LOG_NOTICE /* Default priority for syslog facility */
#define TELL(fh) lseek(fh, 0, SEEK_CUR)
#ifdef OS_WINNT
#define TRUNCATE(fh) chsize(fh, TELL(fh))
#else
#define TRUNCATE(fh) ftruncate(fh, TELL(fh))
#endif
#define NAME_LENGTH 1500
#define DEFAULT_TIME_FORMAT "%c"
#define DEFAULT_DATE_FORMAT "%x"
#define DEFAULT_HTTP_CHARSET "ISO-8859-1"
#define SUCCESS 1
#define FAILURE 0
#define EL_SUCCESS 1
#define EL_FIRST_MSG 2
#define EL_LAST_MSG 3
#define EL_NO_MSG 4
#define EL_FILE_ERROR 5
#define EL_UPGRADE 6
#define EL_EMPTY 7
#define EL_MEM_ERROR 8
#define EL_DUPLICATE 9
#define EL_INVAL_FILE 10
#define EL_FIRST 1
#define EL_LAST 2
#define EL_NEXT 3
#define EL_PREV 4
#define MAX_GROUPS 32
#define MAX_PARAM 120
#define MAX_ATTACHMENTS 50
#define MAX_N_LIST 100
#define MAX_N_ATTR 100
#define MAX_N_EMAIL 500
#define MAX_REPLY_TO 100
#define CMD_SIZE 10000
#define TEXT_SIZE 250000
#define MAX_PATH_LENGTH 256
#define MAX_CONTENT_LENGTH 10*1024*1024
/* attribute flags */
#define AF_REQUIRED (1<<0)
#define AF_LOCKED (1<<1)
#define AF_MULTI (1<<2)
#define AF_FIXED_EDIT (1<<3)
#define AF_FIXED_REPLY (1<<4)
#define AF_ICON (1<<5)
#define AF_RADIO (1<<6)
#define AF_EXTENDABLE (1<<7)
#define AF_DATE (1<<8)
#define AF_DATETIME (1<<9)
#define AF_TIME (1<<10)
#define AF_NUMERIC (1<<11)
#define AF_USERLIST (1<<12)
#define AF_MUSERLIST (1<<13)
#define AF_USEREMAIL (1<<14)
#define AF_MUSEREMAIL (1<<15)
/* attribute format flags */
#define AFF_SAME_LINE 1
#define AFF_MULTI_LINE 2
#define AFF_DATE 4
#define AFF_EXTENDABLE 8
typedef struct {
int message_id;
char file_name[32];
time_t file_time;
int offset;
int in_reply_to;
unsigned char md5_digest[16];
} EL_INDEX;
typedef struct {
char name[256];
char name_enc[256];
char data_dir[256];
char top_group[256];
EL_INDEX *el_index;
int *n_el_index;
int n_attr;
PMXML_NODE pwd_xml_tree;
} LOGBOOK;
typedef struct {
int message_id;
unsigned char md5_digest[16];
} MD5_INDEX;
typedef struct LBNODE *LBLIST;
struct LBNODE {
char name[256];
LBLIST *member;
int n_members;
int is_top;
} LBNODE;
typedef struct {
LOGBOOK *lbs;
int index;
char string[256];
int number;
int in_reply_to;
} MSG_LIST;
typedef struct {
char user_name[256];
char session_id[32];
char host_ip[32];
time_t time;
} SESSION_ID;
void show_error(char *error);
int is_verbose(void);
extern void eprintf(const char *, ...);
BOOL enum_user_line(LOGBOOK * lbs, int n, char *user, int size);
int get_user_line(LOGBOOK * lbs, char *user, char *password, char *full_name, char *email,
BOOL email_notify[1000], time_t * last_access, int *inactive);
int get_full_name(LOGBOOK *lbs, char *uname, char *full_name);
int set_user_inactive(LOGBOOK * lbs, char *user, int inactive);
int strbreak(char *str, char list[][NAME_LENGTH], int size, char *brk, BOOL ignore_quotes);
int execute_shell(LOGBOOK * lbs, int message_id, char attrib[MAX_N_ATTR][NAME_LENGTH],
char att_file[MAX_ATTACHMENTS][256], char *sh_cmd);
BOOL isparam(char *param);
char *getparam(char *param);
void write_logfile(LOGBOOK * lbs, const char *str);
BOOL check_login_user(LOGBOOK * lbs, char *user);
LBLIST get_logbook_hierarchy(void);
BOOL is_logbook_in_group(LBLIST pgrp, char *logbook);
BOOL is_admin_user(char *logbook, char *user);
BOOL is_admin_user_global(char *user);
void free_logbook_hierarchy(LBLIST root);
void show_top_text(LOGBOOK * lbs);
void show_bottom_text(LOGBOOK * lbs);
int set_attributes(LOGBOOK * lbs, char attributes[][NAME_LENGTH], int n);
void show_elog_list(LOGBOOK * lbs, int past_n, int last_n, int page_n, BOOL default_page, char *info);
int change_config_line(LOGBOOK * lbs, char *option, char *old_value, char *new_value);
int read_password(char *pwd, int size);
int getcfg(char *group, char *param, char *value, int vsize);
int build_subst_list(LOGBOOK * lbs, char list[][NAME_LENGTH], char value[][NAME_LENGTH],
char attrib[][NAME_LENGTH], BOOL format_date);
void highlight_searchtext(regex_t * re_buf, char *src, char *dst, BOOL hidden);
int parse_config_file(char *config_file);
PMXML_NODE load_password_file(LOGBOOK * lbs, char *error, int error_size);
int load_password_files();
void compose_base_url(LOGBOOK * lbs, char *base_url, int size, BOOL email_notify);
void show_elog_entry(LOGBOOK * lbs, char *dec_path, char *command);
char *loc(char *orig);
void strencode(char *text);
void strencode_nouml(char *text);
int scan_attributes(char *logbook);
int is_inline_attachment(char *encoding, int message_id, char *text, int i, char *att);
int setgroup(char *str);
int setuser(char *str);
int setegroup(char *str);
int seteuser(char *str);
void strencode2(char *b, const char *text, int size);
void load_config_section(char *section, char **buffer, char *error);
void remove_crlf(char *buffer);
time_t convert_date(char *date_string);
time_t convert_datetime(char *date_string);
int get_thumb_name(const char *file_name, char *thumb_name, int size, int index);
int create_thumbnail(LOGBOOK * lbs, char *file_name);
int ascii_compare(const void *s1, const void *s2);
int ascii_compare2(const void *s1, const void *s2);
void do_crypt(const char *s, char *d, int size);
BOOL get_password_file(LOGBOOK * lbs, char *file_name, int size);
/* functions from auth.c */
int auth_verify_password(LOGBOOK *lbs, const char *user, const char *password);
int auth_change_password(LOGBOOK *lbs, const char *user, const char *old_pwd, const char *new_pwd, char *error_str, int error_size);
int auth_verify_password_krb5(LOGBOOK *lbs, const char *user, const char *password);
int auth_change_password_krb5(LOGBOOK *lbs, const char *user, const char *old_pwd, const char *new_pwd, char *error, int error_size);