Merge lp:~sergei.glushchenko/percona-pam-for-mysql/BT32086-bug1160348 into lp:percona-pam-for-mysql
- BT32086-bug1160348
- Merge into percona-pam-for-mysql
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Laurynas Biveinis | ||||||||||||
Approved revision: | 29 | ||||||||||||
Merged at revision: | 29 | ||||||||||||
Proposed branch: | lp:~sergei.glushchenko/percona-pam-for-mysql/BT32086-bug1160348 | ||||||||||||
Merge into: | lp:percona-pam-for-mysql | ||||||||||||
Diff against target: |
515 lines (+226/-88) 10 files modified
CMakeLists.txt (+2/-2) configure.ac (+2/-5) src/Makefile.am (+6/-3) src/auth_mapping.c (+53/-61) src/auth_mapping.h (+2/-7) src/auth_pam.c (+2/-1) src/auth_pam_common.c (+6/-8) src/auth_pam_compat.c (+2/-1) src/groups.c (+98/-0) src/groups.h (+53/-0) |
||||||||||||
To merge this branch: | bzr merge lp:~sergei.glushchenko/percona-pam-for-mysql/BT32086-bug1160348 | ||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Laurynas Biveinis (community) | Approve | ||
Review via email:
|
Commit message
Description of the change
This adds support for supplementary groups to PAM plugin user mapping. getgrouplist is used to obtain full list of groups user belongs to. If user is a member of several mapped groups, the group which is listed in authentication string first will be taken.
Also minor issues were addressed, such as copyright changed in files, broken link was removed, libmysqlclient is taken from mysql_config output.
Tested on CentOS 5 with PAM Unix and Mac OS X 10.7 with Open Directory.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
Laurynas,
I don't like current concept of test cases for PAM. They are very intrusive. They add users and groups, create files in /etc and so on. Is there any chance that we revisit it in future?
I believe that tests should be easy to run by every user who downloaded and built software. Current approach makes it very hard to do. One should either run test suite as root or manually setup users and groups. Also there is no cleanup at all. It means that created user accounts remain after test is finished which is not good at all.
Can't we use some kind of mocks or stubs for NSS lookups and PAM functions?
We also could easily cover large of the code by unit tests.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Laurynas Biveinis (laurynas-biveinis) wrote : | # |
The current test cases are meant to be run in VMs, and as such they get their job done. I don't see a problem with extending the current testcases first, I don't think the current MP is the right place/time to pursue the alternatives.
For alternatives in general we can do what MariaDB did, i.e. a mock PAM module.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Sergei Glushchenko (sergei.glushchenko) wrote : | # |
So, for every new test case I have to create issue in "Percona Dev Services" board to change Jenkins configuration. In this case I need a user to be created and added to several groups. I find that it is not convenient.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Laurynas Biveinis (laurynas-biveinis) wrote : | # |
Sergei -
Please create an issue "consider migrating away from VM-based PAM testing" instead.
To work with the current tests, please have a look at test/dbqp/
Preview Diff
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2012-06-13 04:13:02 +0000 | |||
3 | +++ CMakeLists.txt 2013-06-06 14:09:25 +0000 | |||
4 | @@ -1,4 +1,4 @@ | |||
6 | 1 | # (C) 2011 Percona Inc. | 1 | # (C) 2011-2013 Percona Ireland Ltd. |
7 | 2 | # | 2 | # |
8 | 3 | # This program is free software; you can redistribute it and/or modify | 3 | # This program is free software; you can redistribute it and/or modify |
9 | 4 | # it under the terms of the GNU General Public License as published by | 4 | # it under the terms of the GNU General Public License as published by |
10 | @@ -23,7 +23,7 @@ | |||
11 | 23 | IF(HAVE_PAM AND HAVE_MYSQLCLIENT AND HAVE_GETPWNAM_R AND HAVE_GETGRGID_R) | 23 | IF(HAVE_PAM AND HAVE_MYSQLCLIENT AND HAVE_GETPWNAM_R AND HAVE_GETGRGID_R) |
12 | 24 | SET(AUTH_PAM_COMMON_SOURCES | 24 | SET(AUTH_PAM_COMMON_SOURCES |
13 | 25 | src/auth_pam_common.c src/lib_auth_pam_client.c src/lib_auth_pam_client.h | 25 | src/auth_pam_common.c src/lib_auth_pam_client.c src/lib_auth_pam_client.h |
15 | 26 | src/auth_mapping.h src/auth_mapping.c) | 26 | src/auth_mapping.h src/auth_mapping.c src/groups.c src/groups.h) |
16 | 27 | SET(AUTH_PAM_SOURCES ${AUTH_PAM_COMMON_SOURCES} src/auth_pam.c) | 27 | SET(AUTH_PAM_SOURCES ${AUTH_PAM_COMMON_SOURCES} src/auth_pam.c) |
17 | 28 | SET(AUTH_PAM_COMPAT_SOURCES ${AUTH_PAM_COMMON_SOURCES} src/auth_pam_compat.c) | 28 | SET(AUTH_PAM_COMPAT_SOURCES ${AUTH_PAM_COMMON_SOURCES} src/auth_pam_compat.c) |
18 | 29 | MYSQL_ADD_PLUGIN(auth_pam ${AUTH_PAM_SOURCES} LINK_LIBRARIES pam) | 29 | MYSQL_ADD_PLUGIN(auth_pam ${AUTH_PAM_SOURCES} LINK_LIBRARIES pam) |
19 | 30 | 30 | ||
20 | === modified file 'configure.ac' | |||
21 | --- configure.ac 2012-02-10 04:21:32 +0000 | |||
22 | +++ configure.ac 2013-06-06 14:09:25 +0000 | |||
23 | @@ -1,5 +1,5 @@ | |||
24 | 1 | # -*- Autoconf -*- | 1 | # -*- Autoconf -*- |
26 | 2 | # (C) 2011 Percona Inc. | 2 | # (C) 2011-2013 Percona Ireland Ltd. |
27 | 3 | # | 3 | # |
28 | 4 | # This program is free software; you can redistribute it and/or modify | 4 | # This program is free software; you can redistribute it and/or modify |
29 | 5 | # it under the terms of the GNU General Public License as published by | 5 | # it under the terms of the GNU General Public License as published by |
30 | @@ -46,10 +46,7 @@ | |||
31 | 46 | AC_MSG_ERROR( | 46 | AC_MSG_ERROR( |
32 | 47 | [Unable to find PAM. Please install the PAM development libraries]) | 47 | [Unable to find PAM. Please install the PAM development libraries]) |
33 | 48 | ) | 48 | ) |
38 | 49 | AC_CHECK_LIB([mysqlclient], [mysql_init], [DIALOG_LIBS="$DIALOG_LIBS -lmysqlclient"], | 49 | DIALOG_LIBS="$DIALOG_LIBS "`${MYSQL_CONFIG} --libs_r` |
35 | 50 | AC_MSG_ERROR( | ||
36 | 51 | [Unable to find libmysqlclient. Please install the mysql development libraries]) | ||
37 | 52 | ) | ||
39 | 53 | 50 | ||
40 | 54 | # Replace -I with -isystem for the MySQL header include GCC option to silence | 51 | # Replace -I with -isystem for the MySQL header include GCC option to silence |
41 | 55 | # warnings originating from them | 52 | # warnings originating from them |
42 | 56 | 53 | ||
43 | === modified file 'src/Makefile.am' | |||
44 | --- src/Makefile.am 2012-02-13 06:19:11 +0000 | |||
45 | +++ src/Makefile.am 2013-06-06 14:09:25 +0000 | |||
46 | @@ -1,4 +1,4 @@ | |||
48 | 1 | # (C) 2011 Percona Inc. | 1 | # (C) 2011-2013 Percona Ireland Ltd. |
49 | 2 | # | 2 | # |
50 | 3 | # This program is free software; you can redistribute it and/or modify | 3 | # This program is free software; you can redistribute it and/or modify |
51 | 4 | # it under the terms of the GNU General Public License as published by | 4 | # it under the terms of the GNU General Public License as published by |
52 | @@ -20,11 +20,14 @@ | |||
53 | 20 | plugin_CPPFLAGS = -DMYSQL_DYNAMIC_PLUGIN | 20 | plugin_CPPFLAGS = -DMYSQL_DYNAMIC_PLUGIN |
54 | 21 | plugin_LDFLAGS = -module -avoid-version -shared | 21 | plugin_LDFLAGS = -module -avoid-version -shared |
55 | 22 | 22 | ||
57 | 23 | auth_pam_la_SOURCES = auth_pam_common.c auth_pam.c lib_auth_pam_client.h lib_auth_pam_client.c auth_mapping.c | 23 | auth_pam_la_SOURCES = auth_pam_common.c auth_pam.c lib_auth_pam_client.h \ |
58 | 24 | lib_auth_pam_client.c auth_mapping.c groups.c | ||
59 | 24 | auth_pam_la_CPPFLAGS = $(plugin_CPPFLAGS) | 25 | auth_pam_la_CPPFLAGS = $(plugin_CPPFLAGS) |
60 | 25 | auth_pam_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS) | 26 | auth_pam_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS) |
61 | 26 | 27 | ||
63 | 27 | auth_pam_compat_la_SOURCES = auth_pam_common.c auth_pam_compat.c lib_auth_pam_client.h lib_auth_pam_client.c auth_mapping.c | 28 | auth_pam_compat_la_SOURCES = auth_pam_common.c auth_pam_compat.c \ |
64 | 29 | lib_auth_pam_client.h lib_auth_pam_client.c \ | ||
65 | 30 | auth_mapping.c groups.c | ||
66 | 28 | auth_pam_compat_la_CPPFLAGS = $(plugin_CPPFLAGS) | 31 | auth_pam_compat_la_CPPFLAGS = $(plugin_CPPFLAGS) |
67 | 29 | auth_pam_compat_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS) | 32 | auth_pam_compat_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS) |
68 | 30 | 33 | ||
69 | 31 | 34 | ||
70 | === modified file 'src/auth_mapping.c' | |||
71 | --- src/auth_mapping.c 2012-02-09 16:25:22 +0000 | |||
72 | +++ src/auth_mapping.c 2013-06-06 14:09:25 +0000 | |||
73 | @@ -1,5 +1,5 @@ | |||
74 | 1 | /* | 1 | /* |
76 | 2 | (C) 2012 Percona Inc. | 2 | (C) 2012, 2013 Percona Ireland Ltd. |
77 | 3 | 3 | ||
78 | 4 | This program is free software; you can redistribute it and/or modify | 4 | This program is free software; you can redistribute it and/or modify |
79 | 5 | it under the terms of the GNU General Public License as published by | 5 | it under the terms of the GNU General Public License as published by |
80 | @@ -16,19 +16,13 @@ | |||
81 | 16 | */ | 16 | */ |
82 | 17 | 17 | ||
83 | 18 | #include "auth_mapping.h" | 18 | #include "auth_mapping.h" |
86 | 19 | #include <pwd.h> | 19 | #include "groups.h" |
85 | 20 | #include <grp.h> | ||
87 | 21 | #include <string.h> | 20 | #include <string.h> |
88 | 22 | #include <stdlib.h> | 21 | #include <stdlib.h> |
89 | 23 | #include <ctype.h> | 22 | #include <ctype.h> |
90 | 24 | 23 | ||
91 | 25 | #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) | 24 | #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) |
92 | 26 | 25 | ||
93 | 27 | /** The maximum length of buffer for storing NSS record. NSS will store in | ||
94 | 28 | buffer the whole result of lookup request including user name, | ||
95 | 29 | gecos, etc. */ | ||
96 | 30 | enum { max_nss_name_len = 10240 }; | ||
97 | 31 | |||
98 | 32 | /** Token representation: | 26 | /** Token representation: |
99 | 33 | token type, string repr, length of token */ | 27 | token type, string repr, length of token */ |
100 | 34 | struct token | 28 | struct token |
101 | @@ -50,43 +44,6 @@ | |||
102 | 50 | const char *ptr; | 44 | const char *ptr; |
103 | 51 | }; | 45 | }; |
104 | 52 | 46 | ||
105 | 53 | |||
106 | 54 | /** Lookup NSS database for group name by specified user name. | ||
107 | 55 | On sucess user_group returned, otherwise NULL */ | ||
108 | 56 | char *lookup_user_group (const char *user_name, | ||
109 | 57 | char *user_group, int user_group_len) | ||
110 | 58 | { | ||
111 | 59 | struct passwd pwd, *pwd_result; | ||
112 | 60 | struct group grp, *grp_result; | ||
113 | 61 | char *buf; | ||
114 | 62 | int error; | ||
115 | 63 | |||
116 | 64 | buf= malloc(max_nss_name_len); | ||
117 | 65 | if (buf == NULL) | ||
118 | 66 | return NULL; | ||
119 | 67 | |||
120 | 68 | error= getpwnam_r(user_name, &pwd, buf, max_nss_name_len, &pwd_result); | ||
121 | 69 | if (error != 0 || pwd_result == NULL) | ||
122 | 70 | { | ||
123 | 71 | free(buf); | ||
124 | 72 | return NULL; | ||
125 | 73 | } | ||
126 | 74 | |||
127 | 75 | error= getgrgid_r(pwd_result->pw_gid, | ||
128 | 76 | &grp, buf, max_nss_name_len, &grp_result); | ||
129 | 77 | if (error != 0 || grp_result == NULL) | ||
130 | 78 | { | ||
131 | 79 | free(buf); | ||
132 | 80 | return NULL; | ||
133 | 81 | } | ||
134 | 82 | |||
135 | 83 | strncpy(user_group, grp_result->gr_name, user_group_len); | ||
136 | 84 | user_group[user_group_len]= '\0'; | ||
137 | 85 | free(buf); | ||
138 | 86 | |||
139 | 87 | return user_group; | ||
140 | 88 | } | ||
141 | 89 | |||
142 | 90 | /** Get next token from buf. Returns new buf position. */ | 47 | /** Get next token from buf. Returns new buf position. */ |
143 | 91 | static const char *get_token(struct token *token, | 48 | static const char *get_token(struct token *token, |
144 | 92 | const char *buf) | 49 | const char *buf) |
145 | @@ -147,7 +104,7 @@ | |||
146 | 147 | otherwise NULL */ | 104 | otherwise NULL */ |
147 | 148 | const char *mapping_iter_next(struct mapping_iter *it) | 105 | const char *mapping_iter_next(struct mapping_iter *it) |
148 | 149 | { | 106 | { |
150 | 150 | struct token token[4]; | 107 | struct token token[4]= {{0}}; |
151 | 151 | 108 | ||
152 | 152 | /* read next 4 tokens */ | 109 | /* read next 4 tokens */ |
153 | 153 | it->ptr= get_token(token + 3, | 110 | it->ptr= get_token(token + 3, |
154 | @@ -182,28 +139,63 @@ | |||
155 | 182 | free(it); | 139 | free(it); |
156 | 183 | } | 140 | } |
157 | 184 | 141 | ||
162 | 185 | /** Get value by given key. On success value_buf returned, | 142 | /** Get mapped value for given user name. |
163 | 186 | otherwise NULL */ | 143 | Value is looked up by using all user groups as a key. |
164 | 187 | char *mapping_get_value(const char *key, char *value_buf, int value_buf_len, | 144 | Auth string is iterated only once, while groups are iterated |
165 | 188 | const char *mapping_string) | 145 | for every key-value pair. This is mean than auth string order |
166 | 146 | is dominant. | ||
167 | 147 | |||
168 | 148 | Example: | ||
169 | 149 | |||
170 | 150 | given: | ||
171 | 151 | user "foo" is the member of "wheel", "staff" and "bar". | ||
172 | 152 | auth string is "mysql, root=user1, bar=user2, staff=user3" | ||
173 | 153 | |||
174 | 154 | result is "user2". | ||
175 | 155 | |||
176 | 156 | On success value_buf returned, otherwise NULL */ | ||
177 | 157 | char *mapping_lookup_user(const char *user_name, | ||
178 | 158 | char *value_buf, int value_buf_len, | ||
179 | 159 | const char *mapping_string) | ||
180 | 189 | { | 160 | { |
183 | 190 | struct mapping_iter *it= mapping_iter_new(mapping_string); | 161 | /* Iterate through the key-value list stored in auth_string and |
184 | 191 | int key_len= strlen(key); | 162 | find key (which is interpreted as group name) in the list of groups |
185 | 163 | for specified user. If match is found, store appropriate value in | ||
186 | 164 | the authenticated_as field. */ | ||
187 | 165 | struct groups_iter *group_it; | ||
188 | 166 | struct mapping_iter *keyval_it; | ||
189 | 167 | const char *key; | ||
190 | 168 | const char *group; | ||
191 | 192 | 169 | ||
193 | 193 | if (it == NULL) | 170 | keyval_it= mapping_iter_new(mapping_string); |
194 | 171 | if (keyval_it == NULL) | ||
195 | 194 | return NULL; | 172 | return NULL; |
196 | 195 | 173 | ||
198 | 196 | while (mapping_iter_next(it)) | 174 | group_it= groups_iter_new(user_name); |
199 | 175 | if (group_it == NULL) | ||
200 | 197 | { | 176 | { |
207 | 198 | if (key_len == it->key_len && strncmp(key, it->key, key_len) == 0) | 177 | mapping_iter_free(keyval_it); |
208 | 199 | { | 178 | return NULL; |
209 | 200 | memcpy(value_buf, it->value, MIN(value_buf_len, it->value_len)); | 179 | } |
210 | 201 | value_buf[MIN(value_buf_len, it->value_len)]= '\0'; | 180 | |
211 | 202 | mapping_iter_free(it); | 181 | while ((key= mapping_iter_next(keyval_it)) != NULL) { |
212 | 203 | return value_buf; | 182 | while ((group= groups_iter_next(group_it)) != NULL) { |
213 | 183 | if (keyval_it->key_len == strlen(group) && | ||
214 | 184 | strncmp(key, group, keyval_it->key_len) == 0) { | ||
215 | 185 | /* match is found */ | ||
216 | 186 | memcpy(value_buf, keyval_it->value, | ||
217 | 187 | MIN(value_buf_len, keyval_it->value_len)); | ||
218 | 188 | value_buf[MIN(value_buf_len, keyval_it->value_len)]= '\0'; | ||
219 | 189 | groups_iter_free(group_it); | ||
220 | 190 | mapping_iter_free(keyval_it); | ||
221 | 191 | return value_buf; | ||
222 | 192 | } | ||
223 | 204 | } | 193 | } |
224 | 194 | groups_iter_reset(group_it); | ||
225 | 205 | } | 195 | } |
227 | 206 | mapping_iter_free(it); | 196 | |
228 | 197 | groups_iter_free(group_it); | ||
229 | 198 | mapping_iter_free(keyval_it); | ||
230 | 207 | 199 | ||
231 | 208 | return NULL; | 200 | return NULL; |
232 | 209 | } | 201 | } |
233 | 210 | 202 | ||
234 | === modified file 'src/auth_mapping.h' | |||
235 | --- src/auth_mapping.h 2012-02-13 06:19:11 +0000 | |||
236 | +++ src/auth_mapping.h 2013-06-06 14:09:25 +0000 | |||
237 | @@ -1,7 +1,7 @@ | |||
238 | 1 | #ifndef AUTH_MAPPING_INCLUDED | 1 | #ifndef AUTH_MAPPING_INCLUDED |
239 | 2 | #define AUTH_MAPPING_INCLUDED | 2 | #define AUTH_MAPPING_INCLUDED |
240 | 3 | /* | 3 | /* |
242 | 4 | (C) 2012 Percona Inc. | 4 | (C) 2012, 2013 Percona Ireland Ltd. |
243 | 5 | 5 | ||
244 | 6 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
245 | 7 | it under the terms of the GNU General Public License as published by | 7 | it under the terms of the GNU General Public License as published by |
246 | @@ -31,11 +31,6 @@ | |||
247 | 31 | /** Mapping iterator. It's not exposed outsude */ | 31 | /** Mapping iterator. It's not exposed outsude */ |
248 | 32 | struct mapping_iter; | 32 | struct mapping_iter; |
249 | 33 | 33 | ||
250 | 34 | /** Lookup NSS database for group name by specified user name. | ||
251 | 35 | On sucess user_group returned, otherwise NULL */ | ||
252 | 36 | char *lookup_user_group (const char *user_name, | ||
253 | 37 | char *user_group, int user_group_len); | ||
254 | 38 | |||
255 | 39 | /** Create iterator through mapping string. | 34 | /** Create iterator through mapping string. |
256 | 40 | Initially iterator set to position before first | 35 | Initially iterator set to position before first |
257 | 41 | key-value pair. On success non-NULL pointer returned, otherwise NULL */ | 36 | key-value pair. On success non-NULL pointer returned, otherwise NULL */ |
258 | @@ -59,7 +54,7 @@ | |||
259 | 59 | 54 | ||
260 | 60 | /** Get value by given key. On success value_buf returned, | 55 | /** Get value by given key. On success value_buf returned, |
261 | 61 | otherwise NULL */ | 56 | otherwise NULL */ |
263 | 62 | char *mapping_get_value(const char *key, char *value_buf, int value_buf_len, | 57 | char *mapping_lookup_user(const char *key, char *value_buf, int value_buf_len, |
264 | 63 | const char *mapping_string); | 58 | const char *mapping_string); |
265 | 64 | 59 | ||
266 | 65 | /** Get service name for auth_string. On success buf returned, | 60 | /** Get service name for auth_string. On success buf returned, |
267 | 66 | 61 | ||
268 | === modified file 'src/auth_pam.c' | |||
269 | --- src/auth_pam.c 2012-02-13 06:19:11 +0000 | |||
270 | +++ src/auth_pam.c 2013-06-06 14:09:25 +0000 | |||
271 | @@ -1,5 +1,5 @@ | |||
272 | 1 | /* | 1 | /* |
274 | 2 | (C) 2012 Percona Inc. | 2 | (C) 2012, 2013 Percona Ireland Ltd. |
275 | 3 | 3 | ||
276 | 4 | This program is free software; you can redistribute it and/or modify | 4 | This program is free software; you can redistribute it and/or modify |
277 | 5 | it under the terms of the GNU General Public License as published by | 5 | it under the terms of the GNU General Public License as published by |
278 | @@ -54,6 +54,7 @@ | |||
279 | 54 | #include "config.h" | 54 | #include "config.h" |
280 | 55 | #endif | 55 | #endif |
281 | 56 | 56 | ||
282 | 57 | #include <string.h> | ||
283 | 57 | #include "auth_pam_common.h" | 58 | #include "auth_pam_common.h" |
284 | 58 | 59 | ||
285 | 59 | /** The maximum length of buffered PAM messages, i.e. any messages up to the | 60 | /** The maximum length of buffered PAM messages, i.e. any messages up to the |
286 | 60 | 61 | ||
287 | === modified file 'src/auth_pam_common.c' | |||
288 | --- src/auth_pam_common.c 2012-02-13 06:19:11 +0000 | |||
289 | +++ src/auth_pam_common.c 2013-06-06 14:09:25 +0000 | |||
290 | @@ -1,5 +1,5 @@ | |||
291 | 1 | /* | 1 | /* |
293 | 2 | (C) 2011 Percona Inc. | 2 | (C) 2011-2013 Percona Ireland Ltd. |
294 | 3 | 3 | ||
295 | 4 | This program is free software; you can redistribute it and/or modify | 4 | This program is free software; you can redistribute it and/or modify |
296 | 5 | it under the terms of the GNU General Public License as published by | 5 | it under the terms of the GNU General Public License as published by |
297 | @@ -19,8 +19,10 @@ | |||
298 | 19 | #include "config.h" | 19 | #include "config.h" |
299 | 20 | #endif | 20 | #endif |
300 | 21 | 21 | ||
301 | 22 | #include <string.h> | ||
302 | 22 | #include "auth_pam_common.h" | 23 | #include "auth_pam_common.h" |
303 | 23 | #include "auth_mapping.h" | 24 | #include "auth_mapping.h" |
304 | 25 | #include "groups.h" | ||
305 | 24 | 26 | ||
306 | 25 | /* The server plugin */ | 27 | /* The server plugin */ |
307 | 26 | 28 | ||
308 | @@ -110,7 +112,6 @@ | |||
309 | 110 | struct pam_conv conv_func_info= { &vio_server_conv, &data }; | 112 | struct pam_conv conv_func_info= { &vio_server_conv, &data }; |
310 | 111 | int error; | 113 | int error; |
311 | 112 | char *pam_mapped_user_name; | 114 | char *pam_mapped_user_name; |
312 | 113 | char user_group[MYSQL_USERNAME_LENGTH]; | ||
313 | 114 | char service_name[max_pam_service_name_len]; | 115 | char service_name[max_pam_service_name_len]; |
314 | 115 | 116 | ||
315 | 116 | /* Set service name as specified in auth_string. If no auth_string | 117 | /* Set service name as specified in auth_string. If no auth_string |
316 | @@ -173,13 +174,10 @@ | |||
317 | 173 | info->authenticated_as[MYSQL_USERNAME_LENGTH]= '\0'; | 174 | info->authenticated_as[MYSQL_USERNAME_LENGTH]= '\0'; |
318 | 174 | } | 175 | } |
319 | 175 | 176 | ||
324 | 176 | /* If auth_string specified, then lookup user group, | 177 | if (info->auth_string) |
321 | 177 | get mapped MySQL user name and use it as CURRENT_USER() value */ | ||
322 | 178 | if (info->auth_string && | ||
323 | 179 | lookup_user_group(pam_mapped_user_name, user_group, sizeof(user_group))) | ||
325 | 180 | { | 178 | { |
328 | 181 | mapping_get_value(user_group, info->authenticated_as, | 179 | mapping_lookup_user(pam_mapped_user_name, info->authenticated_as, |
329 | 182 | MYSQL_USERNAME_LENGTH, info->auth_string); | 180 | MYSQL_USERNAME_LENGTH, info->auth_string); |
330 | 183 | } | 181 | } |
331 | 184 | 182 | ||
332 | 185 | error= pam_end(pam_handle, error); | 183 | error= pam_end(pam_handle, error); |
333 | 186 | 184 | ||
334 | === modified file 'src/auth_pam_compat.c' | |||
335 | --- src/auth_pam_compat.c 2012-02-13 06:19:11 +0000 | |||
336 | +++ src/auth_pam_compat.c 2013-06-06 14:09:25 +0000 | |||
337 | @@ -1,5 +1,5 @@ | |||
338 | 1 | /* | 1 | /* |
340 | 2 | (C) 2012 Percona Inc. | 2 | (C) 2012, 2013 Percona Ireland Ltd. |
341 | 3 | 3 | ||
342 | 4 | This program is free software; you can redistribute it and/or modify | 4 | This program is free software; you can redistribute it and/or modify |
343 | 5 | it under the terms of the GNU General Public License as published by | 5 | it under the terms of the GNU General Public License as published by |
344 | @@ -52,6 +52,7 @@ | |||
345 | 52 | #include "config.h" | 52 | #include "config.h" |
346 | 53 | #endif | 53 | #endif |
347 | 54 | 54 | ||
348 | 55 | #include <string.h> | ||
349 | 55 | #include "auth_pam_common.h" | 56 | #include "auth_pam_common.h" |
350 | 56 | 57 | ||
351 | 57 | int auth_pam_client_talk_init(void **talk_data) | 58 | int auth_pam_client_talk_init(void **talk_data) |
352 | 58 | 59 | ||
353 | === added file 'src/groups.c' | |||
354 | --- src/groups.c 1970-01-01 00:00:00 +0000 | |||
355 | +++ src/groups.c 2013-06-06 14:09:25 +0000 | |||
356 | @@ -0,0 +1,98 @@ | |||
357 | 1 | /* | ||
358 | 2 | (C) 2013 Percona Ireland Ltd. | ||
359 | 3 | |||
360 | 4 | This program is free software; you can redistribute it and/or modify | ||
361 | 5 | it under the terms of the GNU General Public License as published by | ||
362 | 6 | the Free Software Foundation; version 2 of the License. | ||
363 | 7 | |||
364 | 8 | This program is distributed in the hope that it will be useful, | ||
365 | 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
366 | 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
367 | 11 | GNU General Public License for more details. | ||
368 | 12 | |||
369 | 13 | You should have received a copy of the GNU General Public License | ||
370 | 14 | along with this program; if not, write to the Free Software | ||
371 | 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
372 | 16 | */ | ||
373 | 17 | |||
374 | 18 | #include <pwd.h> | ||
375 | 19 | #include <grp.h> | ||
376 | 20 | #include <string.h> | ||
377 | 21 | #include <stdlib.h> | ||
378 | 22 | #include <unistd.h> | ||
379 | 23 | |||
380 | 24 | enum { max_nss_name_len = 10240 }; | ||
381 | 25 | enum { max_number_of_groups = 1024 }; | ||
382 | 26 | |||
383 | 27 | /** Groups iterator. It's not exposed outsude */ | ||
384 | 28 | struct groups_iter { | ||
385 | 29 | char buf[max_nss_name_len]; | ||
386 | 30 | gid_t groups[max_number_of_groups]; | ||
387 | 31 | int current_group; | ||
388 | 32 | int ngroups; | ||
389 | 33 | }; | ||
390 | 34 | |||
391 | 35 | /** Create iterator through user groups. | ||
392 | 36 | Initially iterator set to position before first | ||
393 | 37 | group. On success non-NULL pointer returned, otherwise NULL */ | ||
394 | 38 | struct groups_iter *groups_iter_new(const char *user_name) | ||
395 | 39 | { | ||
396 | 40 | struct passwd pwd, *pwd_result; | ||
397 | 41 | int error; | ||
398 | 42 | struct groups_iter *it; | ||
399 | 43 | |||
400 | 44 | it= calloc(1, sizeof(struct groups_iter)); | ||
401 | 45 | if (it == NULL) | ||
402 | 46 | return NULL; | ||
403 | 47 | |||
404 | 48 | error= getpwnam_r(user_name, &pwd, it->buf, max_nss_name_len, &pwd_result); | ||
405 | 49 | if (error != 0 || pwd_result == NULL) | ||
406 | 50 | { | ||
407 | 51 | free(it); | ||
408 | 52 | return NULL; | ||
409 | 53 | } | ||
410 | 54 | |||
411 | 55 | it->ngroups= max_number_of_groups; | ||
412 | 56 | error= getgrouplist(user_name, pwd_result->pw_gid, it->groups, &it->ngroups); | ||
413 | 57 | if (error == -1) | ||
414 | 58 | { | ||
415 | 59 | free(it); | ||
416 | 60 | return NULL; | ||
417 | 61 | } | ||
418 | 62 | |||
419 | 63 | return it; | ||
420 | 64 | } | ||
421 | 65 | |||
422 | 66 | /** Move iterator to next group. | ||
423 | 67 | On success group name is returned, | ||
424 | 68 | otherwise NULL */ | ||
425 | 69 | const char *groups_iter_next(struct groups_iter *it) | ||
426 | 70 | { | ||
427 | 71 | struct group grp, *grp_result; | ||
428 | 72 | int error; | ||
429 | 73 | |||
430 | 74 | if (it->current_group >= it->ngroups) | ||
431 | 75 | return NULL; | ||
432 | 76 | |||
433 | 77 | error= getgrgid_r(it->groups[it->current_group++], | ||
434 | 78 | &grp, it->buf, max_nss_name_len, &grp_result); | ||
435 | 79 | if (error != 0 || grp_result == NULL) | ||
436 | 80 | { | ||
437 | 81 | return NULL; | ||
438 | 82 | } | ||
439 | 83 | |||
440 | 84 | return grp_result->gr_name; | ||
441 | 85 | } | ||
442 | 86 | |||
443 | 87 | /** Make iterator to point to beginning again */ | ||
444 | 88 | void groups_iter_reset(struct groups_iter *it) | ||
445 | 89 | { | ||
446 | 90 | it->current_group= 0; | ||
447 | 91 | } | ||
448 | 92 | |||
449 | 93 | /** Finish iteration and release iterator */ | ||
450 | 94 | void groups_iter_free(struct groups_iter *it) | ||
451 | 95 | { | ||
452 | 96 | free(it); | ||
453 | 97 | } | ||
454 | 98 | |||
455 | 0 | 99 | ||
456 | === added file 'src/groups.h' | |||
457 | --- src/groups.h 1970-01-01 00:00:00 +0000 | |||
458 | +++ src/groups.h 2013-06-06 14:09:25 +0000 | |||
459 | @@ -0,0 +1,53 @@ | |||
460 | 1 | #ifndef AUTH_PAM_GROUPS_INCLUDED | ||
461 | 2 | #define AUTH_PAM_GROUPS_INCLUDED | ||
462 | 3 | /* | ||
463 | 4 | (C) 2013 Percona Ireland Ltd. | ||
464 | 5 | |||
465 | 6 | This program is free software; you can redistribute it and/or modify | ||
466 | 7 | it under the terms of the GNU General Public License as published by | ||
467 | 8 | the Free Software Foundation; version 2 of the License. | ||
468 | 9 | |||
469 | 10 | This program is distributed in the hope that it will be useful, | ||
470 | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
471 | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
472 | 13 | GNU General Public License for more details. | ||
473 | 14 | |||
474 | 15 | You should have received a copy of the GNU General Public License | ||
475 | 16 | along with this program; if not, write to the Free Software | ||
476 | 17 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
477 | 18 | */ | ||
478 | 19 | |||
479 | 20 | /** | ||
480 | 21 | @file | ||
481 | 22 | |||
482 | 23 | PAM authentication for MySQL, interface for groups enumeration. | ||
483 | 24 | |||
484 | 25 | */ | ||
485 | 26 | |||
486 | 27 | #ifdef __cplusplus | ||
487 | 28 | extern "C" { | ||
488 | 29 | #endif | ||
489 | 30 | |||
490 | 31 | struct groups_iter; | ||
491 | 32 | |||
492 | 33 | /** Create iterator through user groups. | ||
493 | 34 | Initially iterator set to position before first | ||
494 | 35 | group. On success non-NULL pointer returned, otherwise NULL */ | ||
495 | 36 | struct groups_iter *groups_iter_new(const char *user_name); | ||
496 | 37 | |||
497 | 38 | /** Move iterator to next group. | ||
498 | 39 | On success group name is returned, | ||
499 | 40 | otherwise NULL */ | ||
500 | 41 | const char *groups_iter_next(struct groups_iter *it); | ||
501 | 42 | |||
502 | 43 | /** Make iterator to point to beginning again */ | ||
503 | 44 | void groups_iter_reset(struct groups_iter *it); | ||
504 | 45 | |||
505 | 46 | /** Finish iteration and release iterator */ | ||
506 | 47 | void groups_iter_free(struct groups_iter *it); | ||
507 | 48 | |||
508 | 49 | #ifdef __cplusplus | ||
509 | 50 | } | ||
510 | 51 | #endif | ||
511 | 52 | |||
512 | 53 | #endif | ||
513 | 0 | 54 | ||
514 | === removed symlink 'test/dbqp/workdir' | |||
515 | === target was u'/dev/shm/qp_workdir_root_e5f64ede-8707-4589-9c7a-fc598c0e2f6f' |
Looks good.
Please convert bug 1160348 to a blueprint for Percona Server, and please consider expanding the PAM Jenkins test setup to handle this.