1 /*
2  * ProFTPD: mod_quotatab_ldap -- a mod_quotatab sub-module for obtaining
3  *                               quota information from an LDAP directory.
4  *
5  * Copyright (c) 2002-2014 TJ Saunders
6  * Copyright (c) 2002-3 John Morrissey
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
21  *
22  * As a special exemption, the respective copyright holders give permission
23  * to link this program with OpenSSL, and distribute the resulting
24  * executable, without including the source code for OpenSSL in the source
25  * distribution.
26  */
27 
28 #include "mod_quotatab.h"
29 
30 module quotatab_ldap_module;
31 
ldaptab_close(quota_table_t * ldaptab)32 static int ldaptab_close(quota_table_t *ldaptab) {
33 
34   /* Nothing really needs to be done here. */
35   return 0;
36 }
37 
ldaptab_lookup(quota_table_t * ldaptab,void * ptr,const char * name,quota_type_t quota_type)38 static unsigned char ldaptab_lookup(quota_table_t *ldaptab, void *ptr,
39     const char *name, quota_type_t quota_type) {
40   char **values = NULL;
41   array_header *ldap_data = NULL;
42   pool *tmp_pool = NULL;
43   cmdtable *ldap_cmdtab = NULL;
44   cmd_rec *ldap_cmd = NULL;
45   modret_t *ldap_res = NULL;
46   quota_limit_t *limit = ptr;
47 
48   if (quota_type != USER_QUOTA) {
49     quotatab_log("error: mod_quotatab_ldap only supports user quotas");
50     return FALSE;
51   }
52 
53   /* Find the cmdtable for the ldap_quota_lookup command. */
54   ldap_cmdtab = pr_stash_get_symbol2(PR_SYM_HOOK, "ldap_quota_lookup", NULL,
55     NULL, NULL);
56   if (ldap_cmdtab == NULL) {
57     quotatab_log("error: unable to find LDAP hook symbol 'ldap_quota_lookup'");
58     return FALSE;
59   }
60 
61   /* Allocate a temporary pool for the duration of this lookup. */
62   tmp_pool = make_sub_pool(ldaptab->tab_pool);
63 
64   /* Prepare the command and call the handler. */
65   ldap_cmd = pr_cmd_alloc(tmp_pool, 1, name);
66   ldap_res = pr_module_call(ldap_cmdtab->m, ldap_cmdtab->handler, ldap_cmd);
67 
68   destroy_pool(tmp_pool);
69 
70   /* Check the results. */
71   if (!ldap_res || MODRET_ISERROR(ldap_res)) {
72     quotatab_log("error performing LDAP search");
73     return FALSE;
74   }
75 
76   ldap_data = (array_header *) ldap_res->data;
77   if (ldap_data->nelts != 9) {
78     quotatab_log("LDAP search returned wrong number of elements");
79     return FALSE;
80   }
81 
82   values = (char **) ldap_data->elts;
83 
84   /* Retrieve the limit record (9 values):
85    *  name
86    *  per_session
87    *  limit_type
88    *  bytes_{in,out,xfer}_avail
89    *  files_{in,out,xfer}_avail
90    */
91 
92   memmove(limit->name, values[0], strlen(values[0]) + 1);
93   limit->quota_type = USER_QUOTA;
94 
95   if (!strcasecmp(values[1], "false"))
96     limit->quota_per_session = FALSE;
97   else if (!strcasecmp(values[1], "true"))
98     limit->quota_per_session = TRUE;
99 
100   if (!strcasecmp(values[2], "soft"))
101     limit->quota_limit_type = SOFT_LIMIT;
102   else if (!strcasecmp(values[2], "hard"))
103     limit->quota_limit_type = HARD_LIMIT;
104 
105   limit->bytes_in_avail   = atof(values[3]);
106   limit->bytes_out_avail  = atof(values[4]);
107   limit->bytes_xfer_avail = atof(values[5]);
108   limit->files_in_avail   = atoi(values[6]);
109   limit->files_out_avail  = atoi(values[7]);
110   limit->files_xfer_avail = atoi(values[8]);
111 
112   return TRUE;
113 }
114 
ldaptab_verify(quota_table_t * ldaptab)115 static unsigned char ldaptab_verify(quota_table_t *ldaptab) {
116 
117   /* Always TRUE. */
118   return TRUE;
119 }
120 
ldaptab_open(pool * parent_pool,quota_tabtype_t tab_type,const char * srcinfo)121 static quota_table_t *ldaptab_open(pool *parent_pool, quota_tabtype_t tab_type,
122     const char *srcinfo) {
123 
124   pool *tab_pool = make_sub_pool(parent_pool);
125   quota_table_t *tab = NULL;
126 
127   tab = (quota_table_t *) pcalloc(tab_pool, sizeof(quota_table_t));
128   tab->tab_pool = tab_pool;
129   tab->tab_type = tab_type;
130 
131   /* Set all the necessary function pointers. */
132   tab->tab_close = ldaptab_close;
133   tab->tab_lookup = ldaptab_lookup;
134   tab->tab_verify = ldaptab_verify;
135 
136   return tab;
137 }
138 
139 /* Event handlers
140  */
141 
142 #if defined(PR_SHARED_MODULE)
ldaptab_mod_unload_ev(const void * event_data,void * user_data)143 static void ldaptab_mod_unload_ev(const void *event_data, void *user_data) {
144   if (strcmp("mod_quotatab_ldap.c", (const char *) event_data) == 0) {
145     pr_event_unregister(&quotatab_ldap_module, NULL, NULL);
146     quotatab_unregister_backend("ldap", QUOTATAB_LIMIT_SRC);
147   }
148 }
149 #endif /* PR_SHARED_MODULE */
150 
151 /* Initialization routines
152  */
153 
ldaptab_init(void)154 static int ldaptab_init(void) {
155   quotatab_register_backend("ldap", ldaptab_open, QUOTATAB_LIMIT_SRC);
156 
157 #if defined(PR_SHARED_MODULE)
158   pr_event_register(&quotatab_ldap_module, "core.module-unload",
159     ldaptab_mod_unload_ev, NULL);
160 #endif /* PR_SHARED_MODULE */
161 
162   return 0;
163 }
164 
165 module quotatab_ldap_module = {
166   NULL, NULL,
167 
168   /* Module API version 2.0 */
169   0x20,
170 
171   /* Module name */
172   "quotatab_ldap",
173 
174   /* Module configuration handler table */
175   NULL,
176 
177   /* Module command handler table */
178   NULL,
179 
180   /* Module authentication handler table */
181   NULL,
182 
183   /* Module initialization function */
184   ldaptab_init,
185 
186   /* Module child initialization function */
187   NULL
188 };
189