HylaFAX The world's most advanced open source fax server

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: [hylafax-users] Hylafax and ldap



hi,


First of all you need ldap development package 
-next you add patch: cd hylafax-xxxx; patch -p1 ../hylafax.-ldap.patch
-next configure hylafax: ./configure
-next change defs and config.h file according to hylafax-ldap.readme file
-next compile hylafax
-next copy ldap.conf to /var/spool/hylafax/etc/ and change according to your 
ldap server
-restart hylafax
-try telnet localhost 4559
scape character is '^]'.
220 localhost server (HylaFAX (tm) Version 4.2cvs-2004-08-04) ready.
user xxxx
331 Password required for xxxx.
pass aaaa
230 User xxxx logged in.

Marcin
diff -urN hylafax-org/hfaxd/HylaFAXServer.h hylafax-ldap/hfaxd/HylaFAXServer.h
--- hylafax-org/hfaxd/HylaFAXServer.h	2004-04-28 10:03:04.000000000 +0200
+++ hylafax-ldap/hfaxd/HylaFAXServer.h	2004-07-23 14:43:02.000000000 +0200
@@ -48,6 +48,25 @@
 }
 #endif // HAVE_PAM
 
+#ifdef HAVE_LDAP
+#include <ldap.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <lber.h>
+#include <iostream.h>
+#include <fstream.h>
+
+extern char sIP [ ];
+extern int iPort;
+extern int iLDAPVersion;
+extern char p_LDAP_Admin_Name [ ];
+extern char p_LDAP_Admin_Passwd [ ];
+extern char p_LDAP_Base [ ];
+int read_ldap_config(const char* pConfig, char* pIP, int* pPort, char* pAdminLogin, char* pAdminPassword, char* pBase, int* pVersion);
+#endif // HAVE_LDAP
+
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <dirent.h>
@@ -355,6 +374,8 @@
     bool userID(const char*, u_int& id);
     void fillIDCache(void);
 
+    bool ldapCheck(const char* user, const char* pass);
+
     bool cvtPasswd(const char* type, const char* pass, fxStr& result);
     bool findUser(FILE* db, const char* user, u_int& newuid);
     bool addUser(FILE* db, const char* user, u_int uid,
@@ -589,7 +610,7 @@
  * business seeing.  Also we implement an access
  * control system that is built on top of the
  * normal UNIX protection mechanisms.
- */ 
+ */
 struct SpoolDir {
     const char*	pathname;
     bool adminOnly;	// accessible by unprivileged clients
diff -urN hylafax-org/hfaxd/Login.c++ hylafax-ldap/hfaxd/Login.c++
--- hylafax-org/hfaxd/Login.c++	2004-04-28 10:03:04.000000000 +0200
+++ hylafax-ldap/hfaxd/Login.c++	2004-07-23 14:43:02.000000000 +0200
@@ -137,6 +137,105 @@
 	return(retval);
 }
 
+/**
+* ldapCheck
+* function checks if user with selected login and password exists in LDAP
+* param user [IN] - pointer to string containing user login
+* param pass [IN] - pointer to string containing user password
+* return true if user exists
+*/
+bool
+HylaFAXServer::ldapCheck( const char* user, const char* pass )
+{
+	bool retval = false;
+#ifdef HAVE_LDAP
+
+	int err;
+	char filter [ 255 ];
+	snprintf( filter, 255, "uid=%s", user );
+	char* pspass;
+	char spass[ 255 ];
+	LDAPMessage* pEntries;
+	LDAPMessage* pEntry;
+	char **p_arr_values;
+	char ldap_conf_file [ 1024 ];
+	LDAP* p_LDAPConn;
+
+	snprintf( ldap_conf_file, 1024, "%s/etc/ldap.conf", FAX_SPOOLDIR ); // create string with configuration file path name
+
+	err = read_ldap_config( ( const char* ) ldap_conf_file, sIP, &iPort, p_LDAP_Admin_Name, p_LDAP_Admin_Passwd, p_LDAP_Base, &iLDAPVersion );
+
+	if ( err == -1 )
+	{
+		reply( 530, "Configuration file not found" );
+		return false;
+	}
+	if ( err == -2 )
+	{
+		reply( 530, "Configuration file incomplete" );
+		return false;
+	}
+
+	p_LDAPConn = ldap_init( sIP, iPort );
+	if ( p_LDAPConn == NULL )
+	{
+		reply( 530, "Unable to connect to LDAP" );
+		return false;
+	}
+	err = ldap_set_option( p_LDAPConn, LDAP_OPT_PROTOCOL_VERSION, ( void * ) & iLDAPVersion );
+	if ( err != LDAP_SUCCESS )
+	{
+		reply( 530, "Set Option LDAP error %d: %s", err, ldap_err2string( err ) );
+		ldap_unbind_s( p_LDAPConn );
+		return false;
+	}
+
+	err = ldap_simple_bind_s( p_LDAPConn, p_LDAP_Admin_Name, p_LDAP_Admin_Passwd );
+	if ( err != LDAP_SUCCESS )
+	{
+		reply( 530, "Bind LDAP error %d: %s", err, ldap_err2string( err ) );
+		ldap_unbind_s( p_LDAPConn );
+		return false;
+	}
+
+	err = ldap_search_s( p_LDAPConn, p_LDAP_Base, LDAP_SCOPE_SUBTREE, filter, NULL, 0, &pEntries );
+	if ( err != LDAP_SUCCESS )
+	{
+		reply( 530, "Search LDAP error %d: %s", err, ldap_err2string( err ) );
+		ldap_unbind_s( p_LDAPConn );
+		return false;
+	}
+	pEntry = ldap_first_entry( p_LDAPConn, pEntries );
+	if ( pEntry == NULL )
+	{
+		reply( 530, "LDAP user not found" );
+		ldap_unbind_s( p_LDAPConn );
+		return false;
+	}
+
+	p_arr_values = ldap_get_values( p_LDAPConn, pEntry, "userPassword" );
+	if ( p_arr_values == NULL )
+	{
+		reply( 530, "LDAP attribute userPassword not found" );
+		ldap_unbind_s( p_LDAPConn );
+		return false;
+	}
+
+	strcpy( spass, p_arr_values[ 0 ] );
+	ldap_value_free( p_arr_values );
+	ldap_unbind_s( p_LDAPConn );
+
+	pspass = spass;
+
+	if ( strncmp( spass, "{crypt}", 7 ) == 0 )
+		pspass += 7;
+
+	retval = ( strcmp( crypt( pass, pspass ), pspass ) == 0 );
+#endif //HAVE_LDAP
+
+	return retval;
+}
+
 bool
 HylaFAXServer::pamCheck(const char* user, const char* pass)
 {
@@ -196,7 +295,11 @@
 	pass++;
     } else
 	state |= S_LREPLIES;
+#ifdef HAVE_LDAP
+    if (pass[0] == '\0' || !(ldapCheck(the_user, pass))) {
+#else
     if (pass[0] == '\0' || !(strcmp(crypt(pass, passwd), passwd) == 0 || pamCheck(the_user, pass))) {
+#endif
 	if (++loginAttempts >= maxLoginAttempts) {
 	    reply(530, "Login incorrect (closing connection).");
 	    logNotice("Repeated login failures for user %s from %s [%s]"
@@ -332,3 +435,5 @@
 	Sys::unlink(clientFIFOName);
     _exit(status);		// beware of flushing buffers after a SIGPIPE
 }
+
+
diff -urN hylafax-org/hfaxd/User.c++ hylafax-ldap/hfaxd/User.c++
--- hylafax-org/hfaxd/User.c++	2004-04-28 10:03:04.000000000 +0200
+++ hylafax-ldap/hfaxd/User.c++	2004-07-23 14:43:02.000000000 +0200
@@ -49,6 +49,177 @@
 gid_t	HylaFAXServer::faxuid = 0;		// reserved fax uid
 #define	FAXUID_RESV	HylaFAXServer::faxuid	// reserved fax uid
 
+#ifdef HAVE_LDAP
+char sIP [ 16 ];
+int iPort;
+int iLDAPVersion;
+char p_LDAP_Admin_Name [ 255 ];
+char p_LDAP_Admin_Passwd [ 255 ];
+char p_LDAP_Base [ 1024 ];
+#endif // HAVE_LDAP
+
+
+#ifdef HAVE_LDAP
+/**
+* read_ldap_config
+* param pConfig [IN] points to configuration file name
+* param pIP [OUT] (attribute "LDAPServerIP") points to buffer which will receive LDAP Server IP (buffer must be large enough - there isn't any overrun protection)
+* param pPort [OUT] (attribute "LDAPServerPort") points to variable which will receive LDAP Server port
+* param pAdminLogin [OUT] (attribute "LDAPAdminName") points to buffer which will receive LDAP Server Admin Login (buffer must be large enough - there isn't any overrun protection)
+* param pAdminPassword [OUT] (attribute "LDAPAdminPasswd") points to buffer which will receive LDAP Server Admin Password (buffer must be large enough - there isn't any overrun protection)
+* param pBase [OUT] (attribute "LDAPBase") points to buffer which will receive LDAP Server Base Node Value (buffer must be large enough - there isn't any overrun protection)
+* param pVersion [OUT] (attribute "LDAPVersion") points to variable which will receive LDAP Server Version to set
+* return 0 - no error occured
+* return -1 - configuration file missing / not found / unable to open
+* return -2 - at least one of output values were not found in configuration file and not set
+* configuration line format: <attribute>':'[' ' | '\t']<value>
+*/
+int read_ldap_config(const char* pConfig, char* pIP, int* pPort, char* pAdminLogin, char* pAdminPassword, char* pBase, int* pVersion)
+{
+    static bool bRead = false;
+    if (bRead)
+	return 0;
+
+    int retval;
+    int cnt = 0;
+    char line [ 1024 ];
+    char* pA, *pB;
+    bool fTrim;
+
+    uid_t ouid = geteuid();
+    seteuid( 0 );
+
+    FILE* stream = fopen((char*) pConfig, "r"); // open configuration file
+
+    int err = errno;
+    seteuid(ouid);
+
+    if (stream == NULL) {
+	return -1;
+    }
+
+    // Parse configuration file
+    while (!feof(stream)) {
+	if (fgets(line, sizeof(line), stream) == NULL)
+	    break;
+
+	fTrim = false;
+	pA = (char*) line;
+	if ( line[strlen(line)-1] == '\n')
+	    line[strlen(line)-1] = 0;
+
+	int len = strlen(line);
+	for (int i = 0; i < len; i++) {
+	    if (fTrim) {
+		if (line[i] == ' ' || line[i] == '\t') {
+		    line[ i ] = 0;
+		    pB = ((char*) line)+i+1;
+		} else
+    		    break;
+    	    }
+	    if (line[i] == ':') {
+		line[i] = 0;
+		fTrim = true;
+		pB = ((char*) line)+i+1;
+	    }
+	}
+	
+        if (strcmp(pA,"LDAPServerIP") == 0) {
+    	    strcpy(pIP, pB);
+	    cnt++;
+	}
+	if (strcmp(pA, "LDAPServerPort") == 0) {
+	    *pPort = atoi(pB);
+	    cnt++;
+	}
+	if (strcmp(pA, "LDAPAdminName") == 0) {
+	    strcpy(pAdminLogin, pB);
+	    cnt++;
+	}
+	if (strcmp(pA, "LDAPAdminPasswd") == 0) {
+	    strcpy(pAdminPassword, pB);
+	    cnt++;
+	}
+	if (strcmp(pA, "LDAPBase") == 0) {
+	    strcpy(pBase, pB);
+	    cnt++;
+	}
+	if (strcmp(pA, "LDAPVersion") == 0) {
+	    *pVersion = atoi( pB );
+	    cnt++;
+	}
+    }
+
+    fclose(stream); // close configuration file
+
+    // end of parsing configuration file
+    if (cnt != 6)
+	return -2;
+
+    bRead = true;
+    return 0;
+}
+#endif // HAVE_LDAP
+
+
+#ifdef HAVE_LDAP
+bool
+HylaFAXServer::checkUser(const char* name)
+{
+    int err;
+    LDAP* p_LDAPConn;
+    char filter [255];
+    
+    snprintf(filter, 255, "uid=%s", name);
+    
+    char* pspass;
+    char spass[255];
+    LDAPMessage* pEntries;
+    bool retval;
+
+    char ldap_conf_file [1024];
+    snprintf(ldap_conf_file, 1024, "%s/etc/ldap.conf", FAX_SPOOLDIR); // create string with configuration file path name
+
+    err = read_ldap_config((const char*) ldap_conf_file, sIP, &iPort, p_LDAP_Admin_Name, p_LDAP_Admin_Passwd, p_LDAP_Base, &iLDAPVersion);
+    if (err == -1) {
+	reply(530, "Configuration file not found");
+	return false;
+    }
+    if (err == -2) {
+	reply(530, "Configuration file incomplete");
+	return false;
+    }
+
+    p_LDAPConn = ldap_init(sIP, iPort);
+    if (p_LDAPConn == NULL) {
+	reply(530, "Unable to connect to LDAP");
+	return false;
+    }
+    err = ldap_set_option(p_LDAPConn, LDAP_OPT_PROTOCOL_VERSION, (void *) & iLDAPVersion);
+    if (err != LDAP_SUCCESS) {
+	reply(530, "Set Option LDAP error %d: %s", err, ldap_err2string(err));
+	ldap_unbind_s(p_LDAPConn);
+	return false;
+    }
+    err = ldap_simple_bind_s(p_LDAPConn, p_LDAP_Admin_Name, p_LDAP_Admin_Passwd);
+    if (err != LDAP_SUCCESS) {
+	reply(530, "Bind LDAP error %d: %s", err, ldap_err2string(err));
+	ldap_unbind_s(p_LDAPConn);
+	return false;
+    }
+    err = ldap_search_s(p_LDAPConn, p_LDAP_Base, LDAP_SCOPE_SUBTREE, filter, NULL, 0, &pEntries);
+    if (err != LDAP_SUCCESS) {
+	reply(530, "Search LDAP error %d: %s", err, ldap_err2string(err));
+	ldap_unbind_s(p_LDAPConn);
+	return false;
+    }
+    retval = (ldap_first_entry(p_LDAPConn, pEntries) != NULL);
+    ldap_unbind_s(p_LDAPConn);
+
+    return retval;
+}
+#else // HAVE_LDAP is not defined
+// previous (original) checkUser function version used by non-LDAP authentication
 bool
 HylaFAXServer::checkUser(const char* name)
 {
@@ -62,6 +233,7 @@
 	    (const char*) userAccessFile, strerror(errno));
     return (check);
 }
+#endif // HAVE_LDAP
 
 static bool
 nextRecord(FILE* db, char line[], u_int size)
1) add #define HAVE_LDAP 1 in config.h
2) add -lldap -llber -lresolv in defs in LDFLAGS....
LDAPServerIP:           192.xxxxxx
LDAPServerPort:         389
LDAPAdminName:          cn=ldapmanager,dc=eulerhermes,dc=pl
LDAPAdminPasswd:        text_password
LDAPBase:               ou=xxx,dc=example,dc=com
LDAPVersion:            3 



Project hosted by iFAX Solutions