Merge lp:~sergei.glushchenko/percona-pam-for-mysql/BT32086-bug1160348 into lp:percona-pam-for-mysql

Proposed by Sergei Glushchenko
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
Reviewer Review Type Date Requested Status
Laurynas Biveinis (community) Approve
Review via email: mp+167766@code.launchpad.net

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.

To post a comment you must log in.
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote :

Looks good.

Please convert bug 1160348 to a blueprint for Percona Server, and please consider expanding the PAM Jenkins test setup to handle this.

review: Approve
Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
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/percona_tests/percona_pam. I don't think there is any need to change Jenkins configuration itself.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2012-06-13 04:13:02 +0000
+++ CMakeLists.txt 2013-06-06 14:09:25 +0000
@@ -1,4 +1,4 @@
1# (C) 2011 Percona Inc.1# (C) 2011-2013 Percona Ireland Ltd.
2#2#
3# This program is free software; you can redistribute it and/or modify3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by4# it under the terms of the GNU General Public License as published by
@@ -23,7 +23,7 @@
23IF(HAVE_PAM AND HAVE_MYSQLCLIENT AND HAVE_GETPWNAM_R AND HAVE_GETGRGID_R)23IF(HAVE_PAM AND HAVE_MYSQLCLIENT AND HAVE_GETPWNAM_R AND HAVE_GETGRGID_R)
24 SET(AUTH_PAM_COMMON_SOURCES 24 SET(AUTH_PAM_COMMON_SOURCES
25 src/auth_pam_common.c src/lib_auth_pam_client.c src/lib_auth_pam_client.h25 src/auth_pam_common.c src/lib_auth_pam_client.c src/lib_auth_pam_client.h
26 src/auth_mapping.h src/auth_mapping.c)26 src/auth_mapping.h src/auth_mapping.c src/groups.c src/groups.h)
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)
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)
29 MYSQL_ADD_PLUGIN(auth_pam ${AUTH_PAM_SOURCES} LINK_LIBRARIES pam)29 MYSQL_ADD_PLUGIN(auth_pam ${AUTH_PAM_SOURCES} LINK_LIBRARIES pam)
3030
=== modified file 'configure.ac'
--- configure.ac 2012-02-10 04:21:32 +0000
+++ configure.ac 2013-06-06 14:09:25 +0000
@@ -1,5 +1,5 @@
1# -*- Autoconf -*-1# -*- Autoconf -*-
2# (C) 2011 Percona Inc.2# (C) 2011-2013 Percona Ireland Ltd.
3#3#
4# This program is free software; you can redistribute it and/or modify4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by5# it under the terms of the GNU General Public License as published by
@@ -46,10 +46,7 @@
46 AC_MSG_ERROR(46 AC_MSG_ERROR(
47 [Unable to find PAM. Please install the PAM development libraries])47 [Unable to find PAM. Please install the PAM development libraries])
48)48)
49AC_CHECK_LIB([mysqlclient], [mysql_init], [DIALOG_LIBS="$DIALOG_LIBS -lmysqlclient"],49DIALOG_LIBS="$DIALOG_LIBS "`${MYSQL_CONFIG} --libs_r`
50 AC_MSG_ERROR(
51 [Unable to find libmysqlclient. Please install the mysql development libraries])
52)
5350
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
55# warnings originating from them52# warnings originating from them
5653
=== modified file 'src/Makefile.am'
--- src/Makefile.am 2012-02-13 06:19:11 +0000
+++ src/Makefile.am 2013-06-06 14:09:25 +0000
@@ -1,4 +1,4 @@
1# (C) 2011 Percona Inc.1# (C) 2011-2013 Percona Ireland Ltd.
2#2#
3# This program is free software; you can redistribute it and/or modify3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by4# it under the terms of the GNU General Public License as published by
@@ -20,11 +20,14 @@
20plugin_CPPFLAGS = -DMYSQL_DYNAMIC_PLUGIN20plugin_CPPFLAGS = -DMYSQL_DYNAMIC_PLUGIN
21plugin_LDFLAGS = -module -avoid-version -shared21plugin_LDFLAGS = -module -avoid-version -shared
2222
23auth_pam_la_SOURCES = auth_pam_common.c auth_pam.c lib_auth_pam_client.h lib_auth_pam_client.c auth_mapping.c23auth_pam_la_SOURCES = auth_pam_common.c auth_pam.c lib_auth_pam_client.h \
24 lib_auth_pam_client.c auth_mapping.c groups.c
24auth_pam_la_CPPFLAGS = $(plugin_CPPFLAGS)25auth_pam_la_CPPFLAGS = $(plugin_CPPFLAGS)
25auth_pam_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS)26auth_pam_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS)
2627
27auth_pam_compat_la_SOURCES = auth_pam_common.c auth_pam_compat.c lib_auth_pam_client.h lib_auth_pam_client.c auth_mapping.c28auth_pam_compat_la_SOURCES = auth_pam_common.c auth_pam_compat.c \
29 lib_auth_pam_client.h lib_auth_pam_client.c \
30 auth_mapping.c groups.c
28auth_pam_compat_la_CPPFLAGS = $(plugin_CPPFLAGS)31auth_pam_compat_la_CPPFLAGS = $(plugin_CPPFLAGS)
29auth_pam_compat_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS)32auth_pam_compat_la_LDFLAGS = $(plugin_LDFLAGS) $(AUTH_PAM_LIBS)
3033
3134
=== modified file 'src/auth_mapping.c'
--- src/auth_mapping.c 2012-02-09 16:25:22 +0000
+++ src/auth_mapping.c 2013-06-06 14:09:25 +0000
@@ -1,5 +1,5 @@
1/*1/*
2(C) 2012 Percona Inc.2(C) 2012, 2013 Percona Ireland Ltd.
33
4This program is free software; you can redistribute it and/or modify4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by5it under the terms of the GNU General Public License as published by
@@ -16,19 +16,13 @@
16*/16*/
1717
18#include "auth_mapping.h"18#include "auth_mapping.h"
19#include <pwd.h>19#include "groups.h"
20#include <grp.h>
21#include <string.h>20#include <string.h>
22#include <stdlib.h>21#include <stdlib.h>
23#include <ctype.h>22#include <ctype.h>
2423
25#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))24#define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
2625
27/** The maximum length of buffer for storing NSS record. NSS will store in
28 buffer the whole result of lookup request including user name,
29 gecos, etc. */
30enum { max_nss_name_len = 10240 };
31
32/** Token representation:26/** Token representation:
33 token type, string repr, length of token */27 token type, string repr, length of token */
34struct token28struct token
@@ -50,43 +44,6 @@
50 const char *ptr;44 const char *ptr;
51};45};
5246
53
54/** Lookup NSS database for group name by specified user name.
55 On sucess user_group returned, otherwise NULL */
56char *lookup_user_group (const char *user_name,
57 char *user_group, int user_group_len)
58{
59 struct passwd pwd, *pwd_result;
60 struct group grp, *grp_result;
61 char *buf;
62 int error;
63
64 buf= malloc(max_nss_name_len);
65 if (buf == NULL)
66 return NULL;
67
68 error= getpwnam_r(user_name, &pwd, buf, max_nss_name_len, &pwd_result);
69 if (error != 0 || pwd_result == NULL)
70 {
71 free(buf);
72 return NULL;
73 }
74
75 error= getgrgid_r(pwd_result->pw_gid,
76 &grp, buf, max_nss_name_len, &grp_result);
77 if (error != 0 || grp_result == NULL)
78 {
79 free(buf);
80 return NULL;
81 }
82
83 strncpy(user_group, grp_result->gr_name, user_group_len);
84 user_group[user_group_len]= '\0';
85 free(buf);
86
87 return user_group;
88}
89
90/** Get next token from buf. Returns new buf position. */47/** Get next token from buf. Returns new buf position. */
91static const char *get_token(struct token *token,48static const char *get_token(struct token *token,
92 const char *buf)49 const char *buf)
@@ -147,7 +104,7 @@
147 otherwise NULL */104 otherwise NULL */
148const char *mapping_iter_next(struct mapping_iter *it)105const char *mapping_iter_next(struct mapping_iter *it)
149{106{
150 struct token token[4];107 struct token token[4]= {{0}};
151108
152 /* read next 4 tokens */109 /* read next 4 tokens */
153 it->ptr= get_token(token + 3,110 it->ptr= get_token(token + 3,
@@ -182,28 +139,63 @@
182 free(it);139 free(it);
183}140}
184141
185/** Get value by given key. On success value_buf returned,142/** Get mapped value for given user name.
186 otherwise NULL */143 Value is looked up by using all user groups as a key.
187char *mapping_get_value(const char *key, char *value_buf, int value_buf_len,144 Auth string is iterated only once, while groups are iterated
188 const char *mapping_string)145 for every key-value pair. This is mean than auth string order
146 is dominant.
147
148 Example:
149
150 given:
151 user "foo" is the member of "wheel", "staff" and "bar".
152 auth string is "mysql, root=user1, bar=user2, staff=user3"
153
154 result is "user2".
155
156 On success value_buf returned, otherwise NULL */
157char *mapping_lookup_user(const char *user_name,
158 char *value_buf, int value_buf_len,
159 const char *mapping_string)
189{160{
190 struct mapping_iter *it= mapping_iter_new(mapping_string);161 /* Iterate through the key-value list stored in auth_string and
191 int key_len= strlen(key);162 find key (which is interpreted as group name) in the list of groups
163 for specified user. If match is found, store appropriate value in
164 the authenticated_as field. */
165 struct groups_iter *group_it;
166 struct mapping_iter *keyval_it;
167 const char *key;
168 const char *group;
192169
193 if (it == NULL)170 keyval_it= mapping_iter_new(mapping_string);
171 if (keyval_it == NULL)
194 return NULL;172 return NULL;
195173
196 while (mapping_iter_next(it))174 group_it= groups_iter_new(user_name);
175 if (group_it == NULL)
197 {176 {
198 if (key_len == it->key_len && strncmp(key, it->key, key_len) == 0)177 mapping_iter_free(keyval_it);
199 {178 return NULL;
200 memcpy(value_buf, it->value, MIN(value_buf_len, it->value_len));179 }
201 value_buf[MIN(value_buf_len, it->value_len)]= '\0';180
202 mapping_iter_free(it);181 while ((key= mapping_iter_next(keyval_it)) != NULL) {
203 return value_buf;182 while ((group= groups_iter_next(group_it)) != NULL) {
183 if (keyval_it->key_len == strlen(group) &&
184 strncmp(key, group, keyval_it->key_len) == 0) {
185 /* match is found */
186 memcpy(value_buf, keyval_it->value,
187 MIN(value_buf_len, keyval_it->value_len));
188 value_buf[MIN(value_buf_len, keyval_it->value_len)]= '\0';
189 groups_iter_free(group_it);
190 mapping_iter_free(keyval_it);
191 return value_buf;
192 }
204 }193 }
194 groups_iter_reset(group_it);
205 }195 }
206 mapping_iter_free(it);196
197 groups_iter_free(group_it);
198 mapping_iter_free(keyval_it);
207199
208 return NULL;200 return NULL;
209}201}
210202
=== modified file 'src/auth_mapping.h'
--- src/auth_mapping.h 2012-02-13 06:19:11 +0000
+++ src/auth_mapping.h 2013-06-06 14:09:25 +0000
@@ -1,7 +1,7 @@
1#ifndef AUTH_MAPPING_INCLUDED1#ifndef AUTH_MAPPING_INCLUDED
2#define AUTH_MAPPING_INCLUDED2#define AUTH_MAPPING_INCLUDED
3/*3/*
4 (C) 2012 Percona Inc.4 (C) 2012, 2013 Percona Ireland Ltd.
55
6 This program is free software; you can redistribute it and/or modify6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by7 it under the terms of the GNU General Public License as published by
@@ -31,11 +31,6 @@
31/** Mapping iterator. It's not exposed outsude */31/** Mapping iterator. It's not exposed outsude */
32struct mapping_iter;32struct mapping_iter;
3333
34/** Lookup NSS database for group name by specified user name.
35 On sucess user_group returned, otherwise NULL */
36char *lookup_user_group (const char *user_name,
37 char *user_group, int user_group_len);
38
39/** Create iterator through mapping string.34/** Create iterator through mapping string.
40 Initially iterator set to position before first35 Initially iterator set to position before first
41 key-value pair. On success non-NULL pointer returned, otherwise NULL */36 key-value pair. On success non-NULL pointer returned, otherwise NULL */
@@ -59,7 +54,7 @@
5954
60/** Get value by given key. On success value_buf returned,55/** Get value by given key. On success value_buf returned,
61 otherwise NULL */56 otherwise NULL */
62char *mapping_get_value(const char *key, char *value_buf, int value_buf_len,57char *mapping_lookup_user(const char *key, char *value_buf, int value_buf_len,
63 const char *mapping_string);58 const char *mapping_string);
6459
65/** Get service name for auth_string. On success buf returned,60/** Get service name for auth_string. On success buf returned,
6661
=== modified file 'src/auth_pam.c'
--- src/auth_pam.c 2012-02-13 06:19:11 +0000
+++ src/auth_pam.c 2013-06-06 14:09:25 +0000
@@ -1,5 +1,5 @@
1/*1/*
2(C) 2012 Percona Inc.2(C) 2012, 2013 Percona Ireland Ltd.
33
4This program is free software; you can redistribute it and/or modify4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by5it under the terms of the GNU General Public License as published by
@@ -54,6 +54,7 @@
54#include "config.h"54#include "config.h"
55#endif55#endif
5656
57#include <string.h>
57#include "auth_pam_common.h"58#include "auth_pam_common.h"
5859
59/** The maximum length of buffered PAM messages, i.e. any messages up to the60/** The maximum length of buffered PAM messages, i.e. any messages up to the
6061
=== modified file 'src/auth_pam_common.c'
--- src/auth_pam_common.c 2012-02-13 06:19:11 +0000
+++ src/auth_pam_common.c 2013-06-06 14:09:25 +0000
@@ -1,5 +1,5 @@
1/*1/*
2(C) 2011 Percona Inc.2(C) 2011-2013 Percona Ireland Ltd.
33
4This program is free software; you can redistribute it and/or modify4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by5it under the terms of the GNU General Public License as published by
@@ -19,8 +19,10 @@
19#include "config.h"19#include "config.h"
20#endif20#endif
2121
22#include <string.h>
22#include "auth_pam_common.h"23#include "auth_pam_common.h"
23#include "auth_mapping.h"24#include "auth_mapping.h"
25#include "groups.h"
2426
25/* The server plugin */27/* The server plugin */
2628
@@ -110,7 +112,6 @@
110 struct pam_conv conv_func_info= { &vio_server_conv, &data };112 struct pam_conv conv_func_info= { &vio_server_conv, &data };
111 int error;113 int error;
112 char *pam_mapped_user_name;114 char *pam_mapped_user_name;
113 char user_group[MYSQL_USERNAME_LENGTH];
114 char service_name[max_pam_service_name_len];115 char service_name[max_pam_service_name_len];
115116
116 /* Set service name as specified in auth_string. If no auth_string117 /* Set service name as specified in auth_string. If no auth_string
@@ -173,13 +174,10 @@
173 info->authenticated_as[MYSQL_USERNAME_LENGTH]= '\0';174 info->authenticated_as[MYSQL_USERNAME_LENGTH]= '\0';
174 }175 }
175176
176 /* If auth_string specified, then lookup user group,177 if (info->auth_string)
177 get mapped MySQL user name and use it as CURRENT_USER() value */
178 if (info->auth_string &&
179 lookup_user_group(pam_mapped_user_name, user_group, sizeof(user_group)))
180 {178 {
181 mapping_get_value(user_group, info->authenticated_as,179 mapping_lookup_user(pam_mapped_user_name, info->authenticated_as,
182 MYSQL_USERNAME_LENGTH, info->auth_string);180 MYSQL_USERNAME_LENGTH, info->auth_string);
183 }181 }
184182
185 error= pam_end(pam_handle, error);183 error= pam_end(pam_handle, error);
186184
=== modified file 'src/auth_pam_compat.c'
--- src/auth_pam_compat.c 2012-02-13 06:19:11 +0000
+++ src/auth_pam_compat.c 2013-06-06 14:09:25 +0000
@@ -1,5 +1,5 @@
1/*1/*
2(C) 2012 Percona Inc.2(C) 2012, 2013 Percona Ireland Ltd.
33
4This program is free software; you can redistribute it and/or modify4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by5it under the terms of the GNU General Public License as published by
@@ -52,6 +52,7 @@
52#include "config.h"52#include "config.h"
53#endif53#endif
5454
55#include <string.h>
55#include "auth_pam_common.h"56#include "auth_pam_common.h"
5657
57int auth_pam_client_talk_init(void **talk_data)58int auth_pam_client_talk_init(void **talk_data)
5859
=== added file 'src/groups.c'
--- src/groups.c 1970-01-01 00:00:00 +0000
+++ src/groups.c 2013-06-06 14:09:25 +0000
@@ -0,0 +1,98 @@
1/*
2(C) 2013 Percona Ireland Ltd.
3
4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License as published by
6the Free Software Foundation; version 2 of the License.
7
8This program is distributed in the hope that it will be useful,
9but WITHOUT ANY WARRANTY; without even the implied warranty of
10MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11GNU General Public License for more details.
12
13You should have received a copy of the GNU General Public License
14along with this program; if not, write to the Free Software
15Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16*/
17
18#include <pwd.h>
19#include <grp.h>
20#include <string.h>
21#include <stdlib.h>
22#include <unistd.h>
23
24enum { max_nss_name_len = 10240 };
25enum { max_number_of_groups = 1024 };
26
27/** Groups iterator. It's not exposed outsude */
28struct groups_iter {
29 char buf[max_nss_name_len];
30 gid_t groups[max_number_of_groups];
31 int current_group;
32 int ngroups;
33};
34
35/** Create iterator through user groups.
36 Initially iterator set to position before first
37 group. On success non-NULL pointer returned, otherwise NULL */
38struct groups_iter *groups_iter_new(const char *user_name)
39{
40 struct passwd pwd, *pwd_result;
41 int error;
42 struct groups_iter *it;
43
44 it= calloc(1, sizeof(struct groups_iter));
45 if (it == NULL)
46 return NULL;
47
48 error= getpwnam_r(user_name, &pwd, it->buf, max_nss_name_len, &pwd_result);
49 if (error != 0 || pwd_result == NULL)
50 {
51 free(it);
52 return NULL;
53 }
54
55 it->ngroups= max_number_of_groups;
56 error= getgrouplist(user_name, pwd_result->pw_gid, it->groups, &it->ngroups);
57 if (error == -1)
58 {
59 free(it);
60 return NULL;
61 }
62
63 return it;
64}
65
66/** Move iterator to next group.
67 On success group name is returned,
68 otherwise NULL */
69const char *groups_iter_next(struct groups_iter *it)
70{
71 struct group grp, *grp_result;
72 int error;
73
74 if (it->current_group >= it->ngroups)
75 return NULL;
76
77 error= getgrgid_r(it->groups[it->current_group++],
78 &grp, it->buf, max_nss_name_len, &grp_result);
79 if (error != 0 || grp_result == NULL)
80 {
81 return NULL;
82 }
83
84 return grp_result->gr_name;
85}
86
87/** Make iterator to point to beginning again */
88void groups_iter_reset(struct groups_iter *it)
89{
90 it->current_group= 0;
91}
92
93/** Finish iteration and release iterator */
94void groups_iter_free(struct groups_iter *it)
95{
96 free(it);
97}
98
099
=== added file 'src/groups.h'
--- src/groups.h 1970-01-01 00:00:00 +0000
+++ src/groups.h 2013-06-06 14:09:25 +0000
@@ -0,0 +1,53 @@
1#ifndef AUTH_PAM_GROUPS_INCLUDED
2#define AUTH_PAM_GROUPS_INCLUDED
3/*
4 (C) 2013 Percona Ireland Ltd.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; version 2 of the License.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18*/
19
20/**
21 @file
22
23 PAM authentication for MySQL, interface for groups enumeration.
24
25*/
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
31struct groups_iter;
32
33/** Create iterator through user groups.
34 Initially iterator set to position before first
35 group. On success non-NULL pointer returned, otherwise NULL */
36struct groups_iter *groups_iter_new(const char *user_name);
37
38/** Move iterator to next group.
39 On success group name is returned,
40 otherwise NULL */
41const char *groups_iter_next(struct groups_iter *it);
42
43/** Make iterator to point to beginning again */
44void groups_iter_reset(struct groups_iter *it);
45
46/** Finish iteration and release iterator */
47void groups_iter_free(struct groups_iter *it);
48
49#ifdef __cplusplus
50}
51#endif
52
53#endif
054
=== removed symlink 'test/dbqp/workdir'
=== target was u'/dev/shm/qp_workdir_root_e5f64ede-8707-4589-9c7a-fc598c0e2f6f'

Subscribers

People subscribed via source and target branches