s/qmail  4.1.18
Next generation secure email transport
checkpassword-ldap.c
Go to the documentation of this file.
1 /* checkpassword-ldap
2  *
3  * checkpassword implementation that searches an LDAP database
4  * for all the necessary parameter.
5  *
6  * Copyright (C) 2003 Scott James Remnant <scott@netsplit.com>.
7  * Copyright (C) 2004 Herve Commowick <hervec@sports.fr>
8  *
9 */
10 
11 #include <sys/types.h>
12 
13 #include <grp.h>
14 #include <pwd.h>
15 #include <errno.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
20 
21 #include <ldap.h>
22 
23 /* Customise these to change the behaviour.
24  * LDAP_HOST hostname of your LDAP server
25  * LDAP_BASE base under which entry must exist
26  * LDAP_SCOPE search scope relative to base
27  * LDAP_FILTER filter to use, must contain two %s which is replaced with the login name and the domain name
28  * LDAP_UID_PARAM name of field containing uid
29  * LDAP_HOME_PARAM name of field containing emplacement of the mailbox
30  * LDAP_BIND_DN dn of the account who has the good permissions to request search
31  * LDAP_BIND_PASSWD password of the account who has the good permissions to request search
32  * MAIL_ACCOUNT_NAME the name of account who reach the mailbox
33  * MAIL_ACCOUNT_UID the uid of account who reach the mailbox
34  * MAIL_ACCOUNT_GID the gid of account who reach the mailbox
35  */
36 
37 #define LDAP_HOST "localhost"
38 #define LDAP_BASE "ou=mail,o=enterprise"
39 #define LDAP_SCOPE LDAP_SCOPE_SUBTREE
40 #define LDAP_FILTER "(&(uid=%s)(dc=%s))"
41 #define LDAP_UID_PARAM "uid"
42 #define LDAP_HOME_PARAM "mailMessageStore"
43 #define LDAP_BIND_DN "uid=auth,ou=mail,o=enterprise"
44 #define LDAP_BIND_PASSWD "password"
45 
46 #define MAIL_ACCOUNT_NAME "mail"
47 #define MAIL_ACCOUNT_UID 8
48 #define MAIL_ACCOUNT_GID 12
49 
50 #define PROTOCOL_LEN 512
51 
52 static int protocol_fd = 3;
55 
56 int _ldap_lookup(void);
57 int _ldap_get_home_param(void);
58 
59 int main (int argc, char *argv[])
60 {
61  struct passwd *pw;
62  FILE *protocol;
63  int uplen, i;
64 
65  prog = argv[0];
66 
67  protocol = fdopen(protocol_fd, "r");
68  if (protocol == NULL) {
69  fprintf(stderr, "%s: error opening protocol fd (%d): %s\n",
70  prog, protocol_fd, strerror(errno));
71  return 100;
72  }
73 
74  uplen = fread(up, 1, PROTOCOL_LEN, protocol);
75 
76  if (uplen == 0) {
77  fprintf(stderr, "%s: bad protocol, zero bytes read\n", prog);
78  return 101;
79  }
80 
81  i = 0;
82  username = up + i;
83  while (up[i++]) {
84  if (i >= uplen) {
85  fprintf(stderr, "%s: bad protocol, no username\n",
86  prog);
87  return 102;
88  }
89  }
90 
91  password = up + i;
92  while (up[i++]) {
93  if (i >= uplen) {
94  fprintf(stderr, "%s: bad protocol, no password\n",
95  prog);
96  return 103;
97  }
98  }
99 
100  for (i = 0, uplen = strlen(username) ; i < uplen ; i++)
101  {
102  if (username[i] == '@')
103  {
104  user = (char *)malloc(i+1);
105  strncpy(user,username,i);
106  host = (char *)malloc(uplen-i+1);
107  strncpy(host,username +i +1,uplen-i);
108  break;
109  }
110  }
111  if ((user == NULL) || (host == NULL))
112  return 1;
113 
114  if (_ldap_lookup())
115  return 1;
116 
117  if (_ldap_get_home_param())
118  return 1;
119 
120  free(user);
121  free(host);
122  free(username);
123 
124  if (argc <= 1)
125  return 0;
126 
127  if (initgroups(MAIL_ACCOUNT_NAME, MAIL_ACCOUNT_GID) != 0) {
128  fprintf(stderr, "%s: unable to set supplementary groups: %s\n",
129  prog, strerror(errno));
130  return 107;
131  }
132 
133  if (setgid(MAIL_ACCOUNT_GID) != 0) {
134  fprintf(stderr, "%s: unable to set gid : %s\n",
135  prog, strerror(errno));
136  return 106;
137  }
138 
139  if (setuid(MAIL_ACCOUNT_UID) != 0) {
140  fprintf(stderr, "%s: unable to set uid : %s\n",
141  prog, strerror(errno));
142  return 105;
143  }
144 
145  if (chdir(homeparam) != 0) {
146  fprintf(stderr, "%s: unable to change to home dir (%s): %s\n",
147  prog, homeparam, strerror(errno));
148  return 108;
149  }
150 
151  execvp(argv[1], argv + 1);
152  fprintf(stderr, "%s: unable to exec %s: %s\n", prog, argv[1],
153  strerror(errno));
154  return 109;
155 }
156 
157 int _ldap_lookup(void)
158 {
159  char *attrs[] = { NULL };
160  char *filter, *dn;
161  char **values;
162  LDAP *ld;
163  LDAPMessage *res, *entry;
164  int ret;
165 
166  ld = ldap_init(LDAP_HOST, LDAP_PORT);
167  if (!ld) {
168  fprintf(stderr, "%s: unable to initialise ldap connection\n",
169  prog);
170  return 1;
171  }
172 
173  ret = ldap_simple_bind_s(ld, LDAP_BIND_DN, LDAP_BIND_PASSWD);
174 
175  if (ret)
176  return 1;
177 
178  filter = malloc(sizeof(LDAP_FILTER) + strlen(user) + strlen(host));
179  sprintf(filter, LDAP_FILTER, user, host);
180 
181  ret = ldap_search_s(ld, LDAP_BASE, LDAP_SCOPE, filter, attrs, 0, &res);
182  if (ret) {
183  fprintf(stderr, "%s: ldap search failed: %s\n", prog,
184  ldap_err2string(ret));
185  return 1;
186  }
187 
188  entry = ldap_first_entry(ld, res);
189 
190 
191  if (!entry)
192  return 1;
193 
194  dn = ldap_get_dn(ld, res);
195 
196  ldap_msgfree(res);
197 
198  ret = ldap_simple_bind_s(ld, dn, password);
199 
200  if (ret)
201  return 1;
202 
203  ldap_memfree(dn);
204  ldap_unbind(ld);
205  return 0;
206 }
207 
209 {
210  char *attrs[] = { NULL };
211  char *filter, *dn;
212  char **values;
213  LDAP *ld;
214  LDAPMessage *res, *entry;
215  int ret;
216 
217  ld = ldap_init(LDAP_HOST, LDAP_PORT);
218  if (!ld) {
219  fprintf(stderr, "%s: unable to initialise ldap connection\n",
220  prog);
221  return 1;
222  }
223 
224  ret = ldap_simple_bind_s(ld, LDAP_BIND_DN, LDAP_BIND_PASSWD);
225  if (ret)
226  return 1;
227 
228  filter = malloc(sizeof(LDAP_FILTER) + strlen(user) + strlen(host));
229  sprintf(filter, LDAP_FILTER, user, host);
230 
231  ret = ldap_search_s(ld, LDAP_BASE, LDAP_SCOPE, filter, attrs, 0, &res);
232 
233  if (ret) {
234  fprintf(stderr, "%s: ldap search failed: %s\n", prog,
235  ldap_err2string(ret));
236  return 1;
237  }
238 
239  entry = ldap_first_entry(ld, res);
240  if (!entry)
241  return 1;
242 
243  values = ldap_get_values(ld, entry, LDAP_HOME_PARAM);
244  if (values && values[0])
245  {
246  homeparam = malloc(strlen(values[0]) + strlen("../../") + 1);
247  strcpy(homeparam,values[0]);
248  strcat(homeparam,"../../");
249  }
250  ldap_msgfree(res);
251  ldap_unbind(ld);
252  return 0;
253 }
int main(int argc, char *argv[])
int _ldap_get_home_param(void)
#define LDAP_FILTER
char * homeparam
char * username
char up[PROTOCOL_LEN]
#define PROTOCOL_LEN
char * user
#define LDAP_BIND_PASSWD
int _ldap_lookup(void)
#define MAIL_ACCOUNT_GID
char * host
#define MAIL_ACCOUNT_NAME
#define MAIL_ACCOUNT_UID
char * prog
char * password
#define LDAP_HOST
#define LDAP_BIND_DN
#define LDAP_SCOPE
#define LDAP_BASE
#define LDAP_HOME_PARAM
struct passwd * pw
Definition: qmail-getpw.c:19
stralloc protocol
Definition: qmail-popup.c:68
int uplen
Definition: qmail-smtpam.c:470