1 /* Copyright 2003-2008 Wang, Chun-Pin All rights reserved. */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <strings.h>
5 #include <syslog.h>
6
7 #include "config.h"
8 #include "auth_int.h"
9
10 typedef struct smbftpd_auth_method {
11 const char *name;
12 int (*config_parse)(const char *file);
13 int (*check)(const char *user, const char *password);
14 void (*config_free)(void);
15 int (*is_user_in_group)(const char *user, const char *group);
16 char *(*get_home)(const char *user);
17 } smbftpd_auth_method_t;
18
19 static smbftpd_auth_method_t auth_list[] = {
20 { "unix", auth_unix_config_parse, auth_unix_check, auth_unix_config_free,
21 auth_unix_is_user_in_group, auth_unix_get_home },
22 #ifdef USE_PAM
23 { "pam", auth_pam_config_parse, auth_pam_check, auth_pam_config_free,
24 auth_pam_is_user_in_group, auth_pam_get_home },
25 #endif
26 { "text", auth_text_config_parse, auth_text_check, auth_text_config_free,
27 auth_text_is_user_in_group, auth_text_get_home },
28 #ifdef WITH_MYSQL
29 { "mysql", auth_mysql_config_parse, auth_mysql_check, auth_mysql_config_free,
30 auth_mysql_is_user_in_group, auth_mysql_get_home },
31 #endif
32 #ifdef WITH_PGSQL
33 { "pgsql", auth_pgsql_config_parse, auth_pgsql_check, auth_pgsql_config_free,
34 auth_pgsql_is_user_in_group, auth_pgsql_get_home },
35 #endif
36 { NULL, NULL, NULL, NULL }
37 };
38
39 static smbftpd_auth_method_t *auth_method;
40
41 /**
42 * Parse and the authentication method config file.
43 *
44 * @param method Authentication method. Could be "unix", "pam", "mysql", "pgsql",
45 * or "smbftpd".
46 * @param path The configuration file of the auth method. It should be a full path.
47 *
48 * @return 0: Success
49 * -1: Failed
50 */
smbftpd_auth_config_parse(const char * method,const char * path)51 int smbftpd_auth_config_parse(const char *method, const char *path)
52 {
53 if (!auth_method) {
54 auth_method = auth_list;
55 }
56
57 while (auth_method && auth_method->name) {
58 if (strcasecmp(auth_method->name, method) == 0) {
59 break;
60 }
61 auth_method++;
62 }
63
64 if (!auth_method || !auth_method->name) {
65 syslog(LOG_ERR, "Authentication method (%s) not found.", method);
66 return -1;
67 }
68
69 if (0 != auth_method->config_parse(path)) {
70 return -1;
71 }
72
73 return 0;
74 }
75
76 /**
77 * Perform user/password checking for the authentication method.
78 *
79 * For pam and unix authentication, it also check expired time.
80 *
81 * @param user Username
82 * @param password Password
83 *
84 * @return 0: Pass authentication
85 * -1: Authentication failed. Either user/pass not match or system failed.
86 */
smbftpd_auth_check(const char * user,const char * password)87 int smbftpd_auth_check(const char *user, const char *password)
88 {
89 if (!auth_method || !auth_method->check) {
90 syslog(LOG_ERR, "%s (%d) Please do smbftpd_auth_init_config() first.", __FILE__, __LINE__);
91 return -1;
92 }
93
94 if (0 == auth_method->check(user, password)) {
95 return 0;
96 } else {
97 return -1;
98 }
99 }
100
101 /**
102 * Perform necessary action after authentication finished or program exists.
103 */
smbftpd_auth_config_free()104 void smbftpd_auth_config_free()
105 {
106 if (!auth_method || !auth_method->config_free) {
107 return;
108 }
109 auth_method->config_free();
110
111 return;
112 }
113
114 /**
115 * Check whether user belongs to the group.
116 *
117 * We will check this by different authentication method. For example,
118 * if we are using UNIX or PAM authentication, we will use getpwnam()
119 * and getgrnam() to check groups. If we are using database authentication,
120 * we will just check the group in database.
121 *
122 * @param user The user name to check
123 * @param group The group name to check
124 *
125 * @return 1: Yes, user belongs to the group
126 * 0: No, user does not belongs to the group or system failed
127 */
smbftpd_auth_is_user_in_group(const char * user,const char * group)128 int smbftpd_auth_is_user_in_group(const char *user, const char *group)
129 {
130 if (!auth_method || !auth_method->is_user_in_group) {
131 return 0;
132 }
133 return auth_method->is_user_in_group(user, group);
134 }
135
136 /**
137 * Get user's home according to different authenticaion method.
138 *
139 * Please note that caller should free() the returned buffer.
140 *
141 * @param user Which user's home to get
142 *
143 * @return A string pointer of home directory or NULL on failed.
144 */
smbftpd_auth_get_home(const char * user)145 char *smbftpd_auth_get_home(const char *user)
146 {
147 if (!auth_method || !auth_method->get_home) {
148 return NULL;
149 }
150 return auth_method->get_home(user);
151 }
152