1 /* Socks Server 5
2  * Copyright (C) 2002 - 2011 by Matteo Ricchetti - <matteo.ricchetti@libero.it>
3 
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18 
19 #include"SS5Main.h"
20 #include"SS5Mod_authorization.h"
21 #include"SS5OpenLdap.h"
22 #include"SS5Mod_log.h"
23 
24 #ifdef SOLARIS
25   #include<lber.h>
26   #define LDAP_DEPRECATED
27 #endif
28 
29 #include <ldap.h>
30 
31 
DirectoryCheck(char * group,char * user)32 UINT DirectoryCheck( char *group, char *user )
33 {
34   register UINT idx1;
35   register UINT idx2;
36 
37   char ntbdomain[64];
38   char ntbuser[64];
39   char swap[64];
40 
41   UINT count;
42 
43   int err = ERR;
44   int pos = 0,
45       gss = 0;
46 
47   pid_t pid;
48 
49   /*
50    *    Get child/thread pid
51    */
52   if( NOTTHREADED() )
53     pid = getpid();
54   else
55     pid = (UINT)(uintmax_t)pthread_self();
56 
57   /*
58    *    Get netbios domain from username
59    */
60   ntbdomain[0]='\0';
61   ntbuser[0]  ='\0';
62   swap[0]  ='\0';
63 
64   for(idx1 = 0, idx2 = 0; user[idx1] && (idx1 < (sizeof(ntbuser) - 1)); idx1++ ) {
65     if( user[idx1] == '\\' || user[idx1] == '@' ) {
66       ntbdomain[idx1] = '\0';
67       pos = 1;
68       gss++;
69       idx1++;
70     }
71 
72     if( pos == 0 ) {
73       ntbdomain[idx1] = user[idx1];
74       ntbuser[idx1] = user[idx1];
75       ntbuser[idx1 + 1] = '\0';
76     }
77     else if( pos == 1 ) {
78       ntbuser[idx2++] = user[idx1];
79       ntbuser[idx2] = '\0';
80     }
81   }
82 
83   /*
84    *    If username in the form user@domain.dom ss5 supposes
85    *    a GSS authentication request
86    */
87   if( gss ) {
88     strncpy(swap,ntbuser,sizeof(swap));
89     strncpy(ntbuser,ntbdomain,sizeof(ntbuser));
90     strncpy(ntbdomain,swap,sizeof(ntbdomain));
91   }
92   /*
93    *    Look for user into all UserStore
94    */
95   for( count = 0; (err == ERR) && (count < NLdapStore); count++ ) {
96     if( SS5SocksOpt.LdapNetbiosDomain ) {
97       /*
98        *    Look for only if user netbios domain and directory netbios domain match
99        */
100       if( STREQ(S5Ldap[count].NtbDomain,"DEF",sizeof("DEF") -1) ) {
101         err = DirectoryQuery(pid, group, ntbuser, count);
102       }
103       else if( STRCASEEQ(S5Ldap[count].NtbDomain,ntbdomain,sizeof(ntbdomain) -1) )
104         err = DirectoryQuery(pid, group, ntbuser, count);
105     }
106     /*
107      *    Look for in order of configuration
108      */
109     else {
110       err = DirectoryQuery( pid, group, ntbuser, count);
111     }
112   }
113   return err;
114 }
115 
DirectoryQuery(pid_t pid,char * group,char * user,int dirid)116 UINT DirectoryQuery( pid_t pid, char *group, char *user, int dirid )
117 {
118   register UINT idx1,idx2;
119 
120   UINT i,l;
121 
122   struct timeval oldapTimeout;
123 
124   char searchFilter[128]="\0";
125   char baseDn[128]      ="\0";
126   char baseTmp[128]     ="\0";
127   char ldap_uri[128]    ="\0";
128 
129   char *attrsList[] = {"dn", NULL };
130 
131   LDAP	*ld      = NULL;
132 
133   LDAPMessage *result;
134 
135   int rc;
136   int protocolVersion = LDAP_VERSION3;
137 
138   char logString[256]="\0";
139 
140   /*
141    *    Set timeout for ldap query
142    */
143   oldapTimeout.tv_sec  = SS5SocksOpt.LdapTimeout;
144   oldapTimeout.tv_usec = 0;
145 
146   /*
147    *    build "searchFilter" for ldap query
148    */
149   if( LDAPBASE() ) {
150     strncpy(searchFilter,S5Ldap[dirid].Filter,sizeof(searchFilter));
151     STRSCAT(searchFilter,"=");
152     STRSCAT(searchFilter,user);
153   }
154   else if( LDAPFILTER() ) {
155     strncpy(searchFilter,"(&(",sizeof(searchFilter));
156     STRSCAT(searchFilter,S5Ldap[dirid].Filter);
157     STRSCAT(searchFilter,"=");
158     STRSCAT(searchFilter,user);
159     STRSCAT(searchFilter,")(");
160     STRSCAT(searchFilter,S5Ldap[dirid].Attribute);
161     STRSCAT(searchFilter,"=");
162     STRSCAT(searchFilter,group);
163     STRSCAT(searchFilter,"))");
164   }
165   /*
166    *    build "base" for ldap query
167    */
168   for(idx1 = 0; (baseDn[idx1] = S5Ldap[dirid].Base[idx1]) != '%' && idx1 < strlen(S5Ldap[dirid].Base); idx1++);
169   baseDn[idx1] = '\0';
170   if( (idx1++) < strlen(S5Ldap[dirid].Base) ) {
171     for(idx2 = 0; (baseTmp[idx2] = S5Ldap[dirid].Base[idx1]) != '\0' && idx1 < strlen(S5Ldap[dirid].Base); idx2++, idx1++);
172     baseTmp[idx2] = '\0';
173 
174     STRSCAT(baseDn,group);
175     STRSCAT(baseDn,baseTmp);
176   }
177 
178   /*
179    *    Initialize ldap environment
180    */
181 #ifdef LDAP_DEPRECATED
182   ld = (LDAP *)ldap_init( S5Ldap[dirid].IP, atoi(S5Ldap[dirid].Port) );
183   if ( ld == NULL ) {
184     ERRNO(pid)
185 
186     return ERR;
187   }
188 #else
189   sprintf(ldap_uri,"ldap://%s:%d/",S5Ldap[dirid].IP,atoi(S5Ldap[dirid].Port));
190   if( ldap_initialize( &ld, ldap_uri) != LDAP_SUCCESS ) {
191     ERRNO(pid)
192 
193     return ERR;
194   }
195 #endif
196 
197   ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &protocolVersion );
198   ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF );
199   /*
200    *    Try to bind into directory
201    */
202   if (( rc = ldap_bind_s( ld, S5Ldap[dirid].Dn, S5Ldap[dirid].Pass, LDAP_AUTH_SIMPLE )) != LDAP_SUCCESS ) {
203     ERRNOLDAP(pid,rc)
204 
205     ldap_unbind( ld );
206     return ERR;
207   }
208   /*
209    *    Search for username into directory
210    */
211   if (( rc = ldap_search_st( ld, baseDn, LDAP_SCOPE_SUBTREE, searchFilter, attrsList, 0, &oldapTimeout, &result )) != LDAP_SUCCESS ) {
212     ERRNOLDAP(pid,rc)
213 
214     ldap_msgfree( result );
215     ldap_unbind( ld );
216 
217     return ERR;
218   }
219   else {
220     /*
221      *    Count entries, if zero NOT FOUND!
222      */
223     if( ldap_count_entries( ld, result ) ) {
224       ldap_msgfree( result );
225       ldap_unbind( ld );
226 
227       return OK;
228     }
229   }
230 
231   ldap_msgfree( result );
232   ldap_unbind( ld );
233 
234   return ERR;
235 }
236 
237