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