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