From 06a87823aaef4ef15854536e822db3f697d3c85e Mon Sep 17 00:00:00 2001 From: Kai Blin Date: Tue, 3 Jul 2007 06:17:39 +0000 Subject: r23675: Build libnss_winbind on linux. (This used to be commit 9b74d3aef41c020846de9ee1f1adc502f4b1bf39) --- source4/nsswitch/winbind_nss_linux.c | 1286 ++++++++++++++++++++++++++++++++++ 1 file changed, 1286 insertions(+) create mode 100644 source4/nsswitch/winbind_nss_linux.c (limited to 'source4/nsswitch/winbind_nss_linux.c') diff --git a/source4/nsswitch/winbind_nss_linux.c b/source4/nsswitch/winbind_nss_linux.c new file mode 100644 index 0000000000..14cf9707e2 --- /dev/null +++ b/source4/nsswitch/winbind_nss_linux.c @@ -0,0 +1,1286 @@ +/* + Unix SMB/CIFS implementation. + + Windows NT Domain nsswitch module + + Copyright (C) Tim Potter 2000 + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +#include "includes.h" +#include "winbind_client.h" + +/* Maximum number of users to pass back over the unix domain socket + per call. This is not a static limit on the total number of users + or groups returned in total. */ + +#define MAX_GETPWENT_USERS 250 +#define MAX_GETGRENT_USERS 250 + +_PUBLIC_ NSS_STATUS _nss_winbind_setpwent(void); +_PUBLIC_ NSS_STATUS _nss_winbind_endpwent(void); +_PUBLIC_ NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer, + size_t buflen, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, + char *buffer, size_t buflen, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result, + char *buffer, size_t buflen, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_setgrent(void); +_PUBLIC_ NSS_STATUS _nss_winbind_endgrent(void); +_PUBLIC_ NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer, + size_t buflen, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer, + size_t buflen, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result, + char *buffer, size_t buflen, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer, + size_t buflen, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, + long int *size, gid_t **groups, + long int limit, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_getusersids(const char *user_sid, char **group_sids, + int *num_groups, char *buffer, size_t buf_size, + int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, char *buffer, + size_t buflen, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, char *buffer, + size_t buflen, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, + size_t buflen, int *errnop); +_PUBLIC_ NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, + size_t buflen, int *errnop); + +/* Prototypes from wb_common.c */ + +extern int winbindd_fd; + +#ifdef DEBUG_NSS +static const char *nss_err_str(NSS_STATUS ret) { + switch (ret) { + case NSS_STATUS_TRYAGAIN: + return "NSS_STATUS_TRYAGAIN"; + case NSS_STATUS_SUCCESS: + return "NSS_STATUS_SUCCESS"; + case NSS_STATUS_NOTFOUND: + return "NSS_STATUS_NOTFOUND"; + case NSS_STATUS_UNAVAIL: + return "NSS_STATUS_UNAVAIL"; + case NSS_STATUS_RETURN: + return "NSS_STATUS_RETURN"; + default: + return "UNKNOWN RETURN CODE!!!!!!!"; + } +} +#endif + +/* Allocate some space from the nss static buffer. The buffer and buflen + are the pointers passed in by the C library to the _nss_ntdom_* + functions. */ + +static char *get_static(char **buffer, size_t *buflen, size_t len) +{ + char *result; + + /* Error check. We return false if things aren't set up right, or + there isn't enough buffer space left. */ + + if ((buffer == NULL) || (buflen == NULL) || (*buflen < len)) { + return NULL; + } + + /* Return an index into the static buffer */ + + result = *buffer; + *buffer += len; + *buflen -= len; + + return result; +} + +/* I've copied the strtok() replacement function next_token() from + lib/util_str.c as I really don't want to have to link in any other + objects if I can possibly avoid it. */ + +static BOOL next_tok(char **ptr,char *buff,const char *sep, size_t bufsize) +{ + char *s; + BOOL quoted; + size_t len=1; + + if (!ptr) return(False); + + s = *ptr; + + /* default to simple separators */ + if (!sep) sep = " \t\n\r"; + + /* find the first non sep char */ + while (*s && strchr(sep,*s)) s++; + + /* nothing left? */ + if (! *s) return(False); + + /* copy over the token */ + for (quoted = False; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++) { + if (*s == '\"') { + quoted = !quoted; + } else { + len++; + *buff++ = *s; + } + } + + *ptr = (*s) ? s+1 : s; + *buff = 0; + + return(True); +} + + +/* Fill a pwent structure from a winbindd_response structure. We use + the static data passed to us by libc to put strings and stuff in. + Return NSS_STATUS_TRYAGAIN if we run out of memory. */ + +static NSS_STATUS fill_pwent(struct passwd *result, + struct winbindd_pw *pw, + char **buffer, size_t *buflen) +{ + /* User name */ + + if ((result->pw_name = + get_static(buffer, buflen, strlen(pw->pw_name) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strlcpy(result->pw_name, pw->pw_name, strlen(pw->pw_name) + 1); + + /* Password */ + + if ((result->pw_passwd = + get_static(buffer, buflen, strlen(pw->pw_passwd) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strlcpy(result->pw_passwd, pw->pw_passwd, strlen(pw->pw_passwd) + 1); + + /* [ug]id */ + + result->pw_uid = pw->pw_uid; + result->pw_gid = pw->pw_gid; + + /* GECOS */ + + if ((result->pw_gecos = + get_static(buffer, buflen, strlen(pw->pw_gecos) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strlcpy(result->pw_gecos, pw->pw_gecos, strlen(pw->pw_gecos) + 1); + + /* Home directory */ + + if ((result->pw_dir = + get_static(buffer, buflen, strlen(pw->pw_dir) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strlcpy(result->pw_dir, pw->pw_dir, strlen(pw->pw_dir) + 1); + + /* Logon shell */ + + if ((result->pw_shell = + get_static(buffer, buflen, strlen(pw->pw_shell) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strlcpy(result->pw_shell, pw->pw_shell, strlen(pw->pw_shell) + 1); + + /* The struct passwd for Solaris has some extra fields which must + be initialised or nscd crashes. */ + +#if HAVE_PASSWD_PW_COMMENT + result->pw_comment = ""; +#endif + +#if HAVE_PASSWD_PW_AGE + result->pw_age = ""; +#endif + + return NSS_STATUS_SUCCESS; +} + +/* Fill a grent structure from a winbindd_response structure. We use + the static data passed to us by libc to put strings and stuff in. + Return NSS_STATUS_TRYAGAIN if we run out of memory. */ + +static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr, + char *gr_mem, char **buffer, size_t *buflen) +{ + fstring name; + int i; + char *tst; + + /* Group name */ + + if ((result->gr_name = + get_static(buffer, buflen, strlen(gr->gr_name) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strlcpy(result->gr_name, gr->gr_name, strlen(gr->gr_name) + 1); + + /* Password */ + + if ((result->gr_passwd = + get_static(buffer, buflen, strlen(gr->gr_passwd) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strlcpy(result->gr_passwd, gr->gr_passwd, strlen(gr->gr_passwd) + 1); + + /* gid */ + + result->gr_gid = gr->gr_gid; + + /* Group membership */ + + if ((gr->num_gr_mem < 0) || !gr_mem) { + gr->num_gr_mem = 0; + } + + /* this next value is a pointer to a pointer so let's align it */ + + /* Calculate number of extra bytes needed to align on pointer size boundry */ + if ((i = (unsigned long)(*buffer) % sizeof(char*)) != 0) + i = sizeof(char*) - i; + + if ((tst = get_static(buffer, buflen, ((gr->num_gr_mem + 1) * + sizeof(char *)+i))) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + result->gr_mem = (char **)(tst + i); + + if (gr->num_gr_mem == 0) { + + /* Group is empty */ + + *(result->gr_mem) = NULL; + return NSS_STATUS_SUCCESS; + } + + /* Start looking at extra data */ + + i = 0; + + while(next_tok((char **)&gr_mem, name, ",", sizeof(fstring))) { + + /* Allocate space for member */ + + if (((result->gr_mem)[i] = + get_static(buffer, buflen, strlen(name) + 1)) == NULL) { + + /* Out of memory */ + + return NSS_STATUS_TRYAGAIN; + } + + strlcpy((result->gr_mem)[i], name, strlen(name) + 1); + i++; + } + + /* Terminate list */ + + (result->gr_mem)[i] = NULL; + + return NSS_STATUS_SUCCESS; +} + +/* + * NSS user functions + */ + +static struct winbindd_response getpwent_response; + +static int ndx_pw_cache; /* Current index into pwd cache */ +static int num_pw_cache; /* Current size of pwd cache */ + +/* Rewind "file pointer" to start of ntdom password database */ + +_PUBLIC_ NSS_STATUS _nss_winbind_setpwent(void) +{ + NSS_STATUS ret; +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: setpwent\n", getpid()); +#endif + + if (num_pw_cache > 0) { + ndx_pw_cache = num_pw_cache = 0; + free_response(&getpwent_response); + } + + ret = winbindd_request(WINBINDD_SETPWENT, NULL, NULL); +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: setpwent returns %s (%d)\n", getpid(), + nss_err_str(ret), ret); +#endif + return ret; +} + +/* Close ntdom password database "file pointer" */ + +_PUBLIC_ NSS_STATUS _nss_winbind_endpwent(void) +{ + NSS_STATUS ret; +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: endpwent\n", getpid()); +#endif + + if (num_pw_cache > 0) { + ndx_pw_cache = num_pw_cache = 0; + free_response(&getpwent_response); + } + + ret = winbindd_request(WINBINDD_ENDPWENT, NULL, NULL); +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: endpwent returns %s (%d)\n", getpid(), + nss_err_str(ret), ret); +#endif + return ret; +} + +/* Fetch the next password entry from ntdom password database */ + +_PUBLIC_ NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, + char *buffer, size_t buflen, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_request request; + static int called_again; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getpwent\n", getpid()); +#endif + + /* Return an entry from the cache if we have one, or if we are + called again because we exceeded our static buffer. */ + + if ((ndx_pw_cache < num_pw_cache) || called_again) { + goto return_result; + } + + /* Else call winbindd to get a bunch of entries */ + + if (num_pw_cache > 0) { + free_response(&getpwent_response); + } + + ZERO_STRUCT(request); + ZERO_STRUCT(getpwent_response); + + request.data.num_entries = MAX_GETPWENT_USERS; + + ret = winbindd_request(WINBINDD_GETPWENT, &request, + &getpwent_response); + + if (ret == NSS_STATUS_SUCCESS) { + struct winbindd_pw *pw_cache; + + /* Fill cache */ + + ndx_pw_cache = 0; + num_pw_cache = getpwent_response.data.num_entries; + + /* Return a result */ + + return_result: + + pw_cache = (struct winbindd_pw *) + getpwent_response.extra_data.data; + + /* Check data is valid */ + + if (pw_cache == NULL) { + ret = NSS_STATUS_NOTFOUND; + goto done; + } + + ret = fill_pwent(result, &pw_cache[ndx_pw_cache], + &buffer, &buflen); + + /* Out of memory - try again */ + + if (ret == NSS_STATUS_TRYAGAIN) { + called_again = True; + *errnop = errno = ERANGE; + goto done; + } + + *errnop = errno = 0; + called_again = False; + ndx_pw_cache++; + + /* If we've finished with this lot of results free cache */ + + if (ndx_pw_cache == num_pw_cache) { + ndx_pw_cache = num_pw_cache = 0; + free_response(&getpwent_response); + } + } + done: +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getpwent returns %s (%d)\n", getpid(), + nss_err_str(ret), ret); +#endif + return ret; +} + +/* Return passwd struct from uid */ + +_PUBLIC_ NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, + char *buffer, size_t buflen, int *errnop) +{ + NSS_STATUS ret; + static struct winbindd_response response; + struct winbindd_request request; + static int keep_response=0; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getpwuid %d\n", getpid(), (unsigned int)uid); +#endif + + /* If our static buffer needs to be expanded we are called again */ + if (!keep_response) { + + /* Call for the first time */ + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + request.data.uid = uid; + + ret = winbindd_request(WINBINDD_GETPWUID, &request, &response); + + if (ret == NSS_STATUS_SUCCESS) { + ret = fill_pwent(result, &response.data.pw, + &buffer, &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = True; + *errnop = errno = ERANGE; + goto done; + } + } + + } else { + + /* We've been called again */ + + ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = True; + *errnop = errno = ERANGE; + goto done; + } + + keep_response = False; + *errnop = errno = 0; + } + + free_response(&response); + done: + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getpwuid %d returns %s (%d)\n", getpid(), + (unsigned int)uid, nss_err_str(ret), ret); +#endif + return ret; +} + +/* Return passwd struct from username */ +_PUBLIC_ NSS_STATUS _nss_winbind_getpwnam_r(const char *name, + struct passwd *result, char *buffer, size_t buflen, int *errnop) +{ + NSS_STATUS ret; + static struct winbindd_response response; + struct winbindd_request request; + static int keep_response; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getpwnam %s\n", getpid(), name); +#endif + + /* If our static buffer needs to be expanded we are called again */ + + if (!keep_response) { + + /* Call for the first time */ + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + strncpy(request.data.username, name, + sizeof(request.data.username) - 1); + request.data.username + [sizeof(request.data.username) - 1] = '\0'; + + ret = winbindd_request(WINBINDD_GETPWNAM, &request, &response); + + if (ret == NSS_STATUS_SUCCESS) { + ret = fill_pwent(result, &response.data.pw, &buffer, + &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = True; + *errnop = errno = ERANGE; + goto done; + } + } + + } else { + + /* We've been called again */ + + ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = True; + *errnop = errno = ERANGE; + goto done; + } + + keep_response = False; + *errnop = errno = 0; + } + + free_response(&response); + done: +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(), + name, nss_err_str(ret), ret); +#endif + return ret; +} + +/* + * NSS group functions + */ + +static struct winbindd_response getgrent_response; + +static int ndx_gr_cache; /* Current index into grp cache */ +static int num_gr_cache; /* Current size of grp cache */ + +/* Rewind "file pointer" to start of ntdom group database */ + +_PUBLIC_ NSS_STATUS _nss_winbind_setgrent(void) +{ + NSS_STATUS ret; +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: setgrent\n", getpid()); +#endif + + if (num_gr_cache > 0) { + ndx_gr_cache = num_gr_cache = 0; + free_response(&getgrent_response); + } + + ret = winbindd_request(WINBINDD_SETGRENT, NULL, NULL); +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: setgrent returns %s (%d)\n", getpid(), + nss_err_str(ret), ret); +#endif + return ret; +} + +/* Close "file pointer" for ntdom group database */ + +_PUBLIC_ NSS_STATUS _nss_winbind_endgrent(void) +{ + NSS_STATUS ret; +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: endgrent\n", getpid()); +#endif + + if (num_gr_cache > 0) { + ndx_gr_cache = num_gr_cache = 0; + free_response(&getgrent_response); + } + + ret = winbindd_request(WINBINDD_ENDGRENT, NULL, NULL); +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(), + nss_err_str(ret), ret); +#endif + return ret; +} + +/* Get next entry from ntdom group database */ + +static NSS_STATUS +winbind_getgrent(enum winbindd_cmd cmd, + struct group *result, + char *buffer, size_t buflen, int *errnop) +{ + NSS_STATUS ret; + static struct winbindd_request request; + static int called_again; + + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getgrent\n", getpid()); +#endif + + /* Return an entry from the cache if we have one, or if we are + called again because we exceeded our static buffer. */ + + if ((ndx_gr_cache < num_gr_cache) || called_again) { + goto return_result; + } + + /* Else call winbindd to get a bunch of entries */ + + if (num_gr_cache > 0) { + free_response(&getgrent_response); + } + + ZERO_STRUCT(request); + ZERO_STRUCT(getgrent_response); + + request.data.num_entries = MAX_GETGRENT_USERS; + + ret = winbindd_request(cmd, &request, + &getgrent_response); + + if (ret == NSS_STATUS_SUCCESS) { + struct winbindd_gr *gr_cache; + int mem_ofs; + + /* Fill cache */ + + ndx_gr_cache = 0; + num_gr_cache = getgrent_response.data.num_entries; + + /* Return a result */ + + return_result: + + gr_cache = (struct winbindd_gr *) + getgrent_response.extra_data.data; + + /* Check data is valid */ + + if (gr_cache == NULL) { + ret = NSS_STATUS_NOTFOUND; + goto done; + } + + /* Fill group membership. The offset into the extra data + for the group membership is the reported offset plus the + size of all the winbindd_gr records returned. */ + + mem_ofs = gr_cache[ndx_gr_cache].gr_mem_ofs + + num_gr_cache * sizeof(struct winbindd_gr); + + ret = fill_grent(result, &gr_cache[ndx_gr_cache], + ((char *)getgrent_response.extra_data.data)+mem_ofs, + &buffer, &buflen); + + /* Out of memory - try again */ + + if (ret == NSS_STATUS_TRYAGAIN) { + called_again = True; + *errnop = errno = ERANGE; + goto done; + } + + *errnop = 0; + called_again = False; + ndx_gr_cache++; + + /* If we've finished with this lot of results free cache */ + + if (ndx_gr_cache == num_gr_cache) { + ndx_gr_cache = num_gr_cache = 0; + free_response(&getgrent_response); + } + } + done: +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getgrent returns %s (%d)\n", getpid(), + nss_err_str(ret), ret); +#endif + return ret; +} + + +_PUBLIC_ NSS_STATUS _nss_winbind_getgrent_r(struct group *result, + char *buffer, size_t buflen, int *errnop) +{ + return winbind_getgrent(WINBINDD_GETGRENT, result, buffer, buflen, errnop); +} + +_PUBLIC_ NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, + char *buffer, size_t buflen, int *errnop) +{ + return winbind_getgrent(WINBINDD_GETGRLST, result, buffer, buflen, errnop); +} + +/* Return group struct from group name */ + +_PUBLIC_ NSS_STATUS _nss_winbind_getgrnam_r(const char *name, + struct group *result, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + static struct winbindd_response response; + struct winbindd_request request; + static int keep_response; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getgrnam %s\n", getpid(), name); +#endif + + /* If our static buffer needs to be expanded we are called again */ + + if (!keep_response) { + + /* Call for the first time */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.groupname, name, + sizeof(request.data.groupname)); + request.data.groupname + [sizeof(request.data.groupname) - 1] = '\0'; + + ret = winbindd_request(WINBINDD_GETGRNAM, &request, &response); + + if (ret == NSS_STATUS_SUCCESS) { + ret = fill_grent(result, &response.data.gr, + (char *)response.extra_data.data, + &buffer, &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = True; + *errnop = errno = ERANGE; + goto done; + } + } + + } else { + + /* We've been called again */ + + ret = fill_grent(result, &response.data.gr, + (char *)response.extra_data.data, &buffer, + &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = True; + *errnop = errno = ERANGE; + goto done; + } + + keep_response = False; + *errnop = 0; + } + + free_response(&response); + done: +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(), + name, nss_err_str(ret), ret); +#endif + return ret; +} + +/* Return group struct from gid */ + +_PUBLIC_ NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, + struct group *result, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + static struct winbindd_response response; + struct winbindd_request request; + static int keep_response; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getgrgid %d\n", getpid(), gid); +#endif + + /* If our static buffer needs to be expanded we are called again */ + + if (!keep_response) { + + /* Call for the first time */ + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + request.data.gid = gid; + + ret = winbindd_request(WINBINDD_GETGRGID, &request, &response); + + if (ret == NSS_STATUS_SUCCESS) { + + ret = fill_grent(result, &response.data.gr, + (char *)response.extra_data.data, + &buffer, &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = True; + *errnop = errno = ERANGE; + goto done; + } + } + + } else { + + /* We've been called again */ + + ret = fill_grent(result, &response.data.gr, + (char *)response.extra_data.data, &buffer, + &buflen); + + if (ret == NSS_STATUS_TRYAGAIN) { + keep_response = True; + *errnop = errno = ERANGE; + goto done; + } + + keep_response = False; + *errnop = 0; + } + + free_response(&response); + done: +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(), + (unsigned int)gid, nss_err_str(ret), ret); +#endif + return ret; +} + +/* Initialise supplementary groups */ + +_PUBLIC_ NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, + long int *start, long int *size, gid_t **groups, + long int limit, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_request request; + struct winbindd_response response; + int i; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: initgroups %s (%d)\n", getpid(), + user, group); +#endif + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.username, user, + sizeof(request.data.username) - 1); + + ret = winbindd_request(WINBINDD_GETGROUPS, &request, &response); + + if (ret == NSS_STATUS_SUCCESS) { + int num_gids = response.data.num_entries; + gid_t *gid_list = (gid_t *)response.extra_data.data; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: initgroups %s: got NSS_STATUS_SUCCESS " + "and %d gids\n", getpid(), + user, num_gids); +#endif + if (gid_list == NULL) { + ret = NSS_STATUS_NOTFOUND; + goto done; + } + + /* Copy group list to client */ + + for (i = 0; i < num_gids; i++) { + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: initgroups %s (%d): " + "processing gid %d \n", getpid(), + user, group, gid_list[i]); +#endif + + /* Skip primary group */ + + if (gid_list[i] == group) { + continue; + } + + /* Filled buffer ? If so, resize. */ + + if (*start == *size) { + long int newsize; + gid_t *newgroups; + + newsize = 2 * (*size); + if (limit > 0) { + if (*size == limit) { + goto done; + } + if (newsize > limit) { + newsize = limit; + } + } + + newgroups = (gid_t *) + realloc((*groups), + newsize * sizeof(**groups)); + if (!newgroups) { + *errnop = ENOMEM; + ret = NSS_STATUS_NOTFOUND; + goto done; + } + *groups = newgroups; + *size = newsize; + } + + /* Add to buffer */ + + (*groups)[*start] = gid_list[i]; + *start += 1; + } + } + + /* Back to your regularly scheduled programming */ + + done: +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: initgroups %s returns %s (%d)\n", getpid(), + user, nss_err_str(ret), ret); +#endif + return ret; +} + + +/* return a list of group SIDs for a user SID */ +_PUBLIC_ NSS_STATUS _nss_winbind_getusersids(const char *user_sid, + char **group_sids, int *num_groups, + char *buffer, size_t buf_size, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_request request; + struct winbindd_response response; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: getusersids %s\n", getpid(), user_sid); +#endif + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.sid, user_sid,sizeof(request.data.sid) - 1); + request.data.sid[sizeof(request.data.sid) - 1] = '\0'; + + ret = winbindd_request(WINBINDD_GETUSERSIDS, &request, &response); + + if (ret != NSS_STATUS_SUCCESS) { + goto done; + } + + if (buf_size < response.length - sizeof(response)) { + ret = NSS_STATUS_TRYAGAIN; + errno = *errnop = ERANGE; + goto done; + } + + *num_groups = response.data.num_entries; + *group_sids = buffer; + memcpy(buffer, response.extra_data.data, response.length - sizeof(response)); + errno = *errnop = 0; + + done: + free_response(&response); + return ret; +} + + +/* map a user or group name to a SID string */ +_PUBLIC_ NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, + char *buffer, size_t buflen, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: nametosid %s\n", getpid(), name); +#endif + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + strncpy(request.data.name.name, name, + sizeof(request.data.name.name) - 1); + request.data.name.name[sizeof(request.data.name.name) - 1] = '\0'; + + ret = winbindd_request(WINBINDD_LOOKUPNAME, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + if (buflen < strlen(response.data.sid.sid)+1) { + ret = NSS_STATUS_TRYAGAIN; + *errnop = errno = ERANGE; + goto failed; + } + + *errnop = errno = 0; + *sid = buffer; + strlcpy(*sid, response.data.sid.sid, strlen(response.data.sid.sid) + 1); + +failed: + free_response(&response); + return ret; +} + +/* map a sid string to a user or group name */ +_PUBLIC_ NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, + char *buffer, size_t buflen, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + static char sep_char; + unsigned needed; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: sidtoname %s\n", getpid(), sid); +#endif + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + /* we need to fetch the separator first time through */ + if (!sep_char) { + ret = winbindd_request(WINBINDD_INFO, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + sep_char = response.data.info.winbind_separator; + free_response(&response); + } + + + strncpy(request.data.sid, sid, + sizeof(request.data.sid) - 1); + request.data.sid[sizeof(request.data.sid) - 1] = '\0'; + + ret = winbindd_request(WINBINDD_LOOKUPSID, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + needed = + strlen(response.data.name.dom_name) + + strlen(response.data.name.name) + 2; + + if (buflen < needed) { + ret = NSS_STATUS_TRYAGAIN; + *errnop = errno = ERANGE; + goto failed; + } + + snprintf(buffer, needed, "%s%c%s", + response.data.name.dom_name, + sep_char, + response.data.name.name); + + *name = buffer; + *errnop = errno = 0; + +failed: + free_response(&response); + return ret; +} + +/* map a sid to a uid */ +_PUBLIC_ NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, + int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: sidtouid %s\n", getpid(), sid); +#endif + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1); + request.data.sid[sizeof(request.data.sid) - 1] = '\0'; + + ret = winbindd_request(WINBINDD_SID_TO_UID, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + *uid = response.data.uid; + +failed: + return ret; +} + +/* map a sid to a gid */ +_PUBLIC_ NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, + int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5d]: sidtogid %s\n", getpid(), sid); +#endif + + ZERO_STRUCT(request); + ZERO_STRUCT(response); + + strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1); + request.data.sid[sizeof(request.data.sid) - 1] = '\0'; + + ret = winbindd_request(WINBINDD_SID_TO_GID, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + *gid = response.data.gid; + +failed: + return ret; +} + +/* map a uid to a SID string */ +_PUBLIC_ NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5u]: uidtosid %u\n", (unsigned int)getpid(), (unsigned int)uid); +#endif + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + request.data.uid = uid; + + ret = winbindd_request(WINBINDD_UID_TO_SID, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + if (buflen < strlen(response.data.sid.sid)+1) { + ret = NSS_STATUS_TRYAGAIN; + *errnop = errno = ERANGE; + goto failed; + } + + *errnop = errno = 0; + *sid = buffer; + strlcpy(*sid, response.data.sid.sid, strlen(response.data.sid.sid) + 1); + +failed: + free_response(&response); + return ret; +} + +/* map a gid to a SID string */ +_PUBLIC_ NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, + size_t buflen, int *errnop) +{ + NSS_STATUS ret; + struct winbindd_response response; + struct winbindd_request request; + +#ifdef DEBUG_NSS + fprintf(stderr, "[%5u]: gidtosid %u\n", (unsigned int)getpid(), (unsigned int)gid); +#endif + + ZERO_STRUCT(response); + ZERO_STRUCT(request); + + request.data.gid = gid; + + ret = winbindd_request(WINBINDD_GID_TO_SID, &request, &response); + if (ret != NSS_STATUS_SUCCESS) { + *errnop = errno = EINVAL; + goto failed; + } + + if (buflen < strlen(response.data.sid.sid)+1) { + ret = NSS_STATUS_TRYAGAIN; + *errnop = errno = ERANGE; + goto failed; + } + + *errnop = errno = 0; + *sid = buffer; + strlcpy(*sid, response.data.sid.sid, strlen(response.data.sid.sid) + 1); + +failed: + free_response(&response); + return ret; +} -- cgit From 95f930d8751f1bcdd7ca9ef23c59b182c1315891 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 02:31:50 +0000 Subject: r23794: convert more code from LGPLv2+ to LGPLv3+ (This used to be commit 9d37f1ec070ddcfd49dfe351e76cc08fa0d9b41c) --- source4/nsswitch/winbind_nss_linux.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'source4/nsswitch/winbind_nss_linux.c') diff --git a/source4/nsswitch/winbind_nss_linux.c b/source4/nsswitch/winbind_nss_linux.c index 14cf9707e2..8a2a045e6a 100644 --- a/source4/nsswitch/winbind_nss_linux.c +++ b/source4/nsswitch/winbind_nss_linux.c @@ -8,17 +8,15 @@ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + You should have received a copy of the GNU Library General Public License + along with this program. If not, see . */ #include "includes.h" -- cgit From b8875bee5f0c5385ba02646c7a8b2380fdfabb7a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 04:04:46 +0000 Subject: r23800: LGPL is now called GNU Lesser General Public License not GNU Library General Public License (This used to be commit 01e3fe7533b5670236c026ec3c6cc1e25655fbc3) --- source4/nsswitch/winbind_nss_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/nsswitch/winbind_nss_linux.c') diff --git a/source4/nsswitch/winbind_nss_linux.c b/source4/nsswitch/winbind_nss_linux.c index 8a2a045e6a..52254b984d 100644 --- a/source4/nsswitch/winbind_nss_linux.c +++ b/source4/nsswitch/winbind_nss_linux.c @@ -6,7 +6,7 @@ Copyright (C) Tim Potter 2000 This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public + modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. @@ -15,7 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. - You should have received a copy of the GNU Library General Public License + You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ -- cgit From 540caf7ea691874436ddfaf440f4b0714e592dce Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 15 Sep 2007 20:09:29 +0000 Subject: r25181: sync winbind client code with samba3 NOTE: wbinfo.c isn't fully merged here metze (This used to be commit eee5327dc2f79c052c2db0ca89f23cc9d2ce355d) --- source4/nsswitch/winbind_nss_linux.c | 277 +++++++++++++++++------------------ 1 file changed, 137 insertions(+), 140 deletions(-) (limited to 'source4/nsswitch/winbind_nss_linux.c') diff --git a/source4/nsswitch/winbind_nss_linux.c b/source4/nsswitch/winbind_nss_linux.c index 52254b984d..ac53979ced 100644 --- a/source4/nsswitch/winbind_nss_linux.c +++ b/source4/nsswitch/winbind_nss_linux.c @@ -19,7 +19,6 @@ along with this program. If not, see . */ -#include "includes.h" #include "winbind_client.h" /* Maximum number of users to pass back over the unix domain socket @@ -29,64 +28,45 @@ #define MAX_GETPWENT_USERS 250 #define MAX_GETGRENT_USERS 250 -_PUBLIC_ NSS_STATUS _nss_winbind_setpwent(void); -_PUBLIC_ NSS_STATUS _nss_winbind_endpwent(void); -_PUBLIC_ NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer, +NSS_STATUS _nss_winbind_setpwent(void); +NSS_STATUS _nss_winbind_endpwent(void); +NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, +NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, size_t buflen, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result, +NSS_STATUS _nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer, size_t buflen, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_setgrent(void); -_PUBLIC_ NSS_STATUS _nss_winbind_endgrent(void); -_PUBLIC_ NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer, +NSS_STATUS _nss_winbind_setgrent(void); +NSS_STATUS _nss_winbind_endgrent(void); +NSS_STATUS _nss_winbind_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer, +NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, char *buffer, size_t buflen, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result, +NSS_STATUS _nss_winbind_getgrnam_r(const char *name, struct group *result, char *buffer, size_t buflen, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer, +NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer, size_t buflen, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, +NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, long int *size, gid_t **groups, long int limit, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_getusersids(const char *user_sid, char **group_sids, +NSS_STATUS _nss_winbind_getusersids(const char *user_sid, char **group_sids, int *num_groups, char *buffer, size_t buf_size, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, char *buffer, +NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, char *buffer, size_t buflen, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, char *buffer, +NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, char *buffer, size_t buflen, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, +NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop); +NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop); +NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, size_t buflen, int *errnop); -_PUBLIC_ NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, +NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, size_t buflen, int *errnop); /* Prototypes from wb_common.c */ extern int winbindd_fd; -#ifdef DEBUG_NSS -static const char *nss_err_str(NSS_STATUS ret) { - switch (ret) { - case NSS_STATUS_TRYAGAIN: - return "NSS_STATUS_TRYAGAIN"; - case NSS_STATUS_SUCCESS: - return "NSS_STATUS_SUCCESS"; - case NSS_STATUS_NOTFOUND: - return "NSS_STATUS_NOTFOUND"; - case NSS_STATUS_UNAVAIL: - return "NSS_STATUS_UNAVAIL"; - case NSS_STATUS_RETURN: - return "NSS_STATUS_RETURN"; - default: - return "UNKNOWN RETURN CODE!!!!!!!"; - } -} -#endif - /* Allocate some space from the nss static buffer. The buffer and buflen are the pointers passed in by the C library to the _nss_ntdom_* functions. */ @@ -115,13 +95,13 @@ static char *get_static(char **buffer, size_t *buflen, size_t len) lib/util_str.c as I really don't want to have to link in any other objects if I can possibly avoid it. */ -static BOOL next_tok(char **ptr,char *buff,const char *sep, size_t bufsize) +static bool next_token(char **ptr,char *buff,const char *sep, size_t bufsize) { char *s; - BOOL quoted; + bool quoted; size_t len=1; - if (!ptr) return(False); + if (!ptr) return false; s = *ptr; @@ -132,10 +112,10 @@ static BOOL next_tok(char **ptr,char *buff,const char *sep, size_t bufsize) while (*s && strchr(sep,*s)) s++; /* nothing left? */ - if (! *s) return(False); + if (! *s) return false; /* copy over the token */ - for (quoted = False; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++) { + for (quoted = false; len < bufsize && *s && (quoted || !strchr(sep,*s)); s++) { if (*s == '\"') { quoted = !quoted; } else { @@ -147,7 +127,7 @@ static BOOL next_tok(char **ptr,char *buff,const char *sep, size_t bufsize) *ptr = (*s) ? s+1 : s; *buff = 0; - return(True); + return true; } @@ -169,7 +149,7 @@ static NSS_STATUS fill_pwent(struct passwd *result, return NSS_STATUS_TRYAGAIN; } - strlcpy(result->pw_name, pw->pw_name, strlen(pw->pw_name) + 1); + strcpy(result->pw_name, pw->pw_name); /* Password */ @@ -181,7 +161,7 @@ static NSS_STATUS fill_pwent(struct passwd *result, return NSS_STATUS_TRYAGAIN; } - strlcpy(result->pw_passwd, pw->pw_passwd, strlen(pw->pw_passwd) + 1); + strcpy(result->pw_passwd, pw->pw_passwd); /* [ug]id */ @@ -198,7 +178,7 @@ static NSS_STATUS fill_pwent(struct passwd *result, return NSS_STATUS_TRYAGAIN; } - strlcpy(result->pw_gecos, pw->pw_gecos, strlen(pw->pw_gecos) + 1); + strcpy(result->pw_gecos, pw->pw_gecos); /* Home directory */ @@ -210,7 +190,7 @@ static NSS_STATUS fill_pwent(struct passwd *result, return NSS_STATUS_TRYAGAIN; } - strlcpy(result->pw_dir, pw->pw_dir, strlen(pw->pw_dir) + 1); + strcpy(result->pw_dir, pw->pw_dir); /* Logon shell */ @@ -222,7 +202,7 @@ static NSS_STATUS fill_pwent(struct passwd *result, return NSS_STATUS_TRYAGAIN; } - strlcpy(result->pw_shell, pw->pw_shell, strlen(pw->pw_shell) + 1); + strcpy(result->pw_shell, pw->pw_shell); /* The struct passwd for Solaris has some extra fields which must be initialised or nscd crashes. */ @@ -259,7 +239,7 @@ static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr, return NSS_STATUS_TRYAGAIN; } - strlcpy(result->gr_name, gr->gr_name, strlen(gr->gr_name) + 1); + strcpy(result->gr_name, gr->gr_name); /* Password */ @@ -271,7 +251,7 @@ static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr, return NSS_STATUS_TRYAGAIN; } - strlcpy(result->gr_passwd, gr->gr_passwd, strlen(gr->gr_passwd) + 1); + strcpy(result->gr_passwd, gr->gr_passwd); /* gid */ @@ -310,7 +290,7 @@ static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr, i = 0; - while(next_tok((char **)&gr_mem, name, ",", sizeof(fstring))) { + while(next_token((char **)&gr_mem, name, ",", sizeof(fstring))) { /* Allocate space for member */ @@ -322,7 +302,7 @@ static NSS_STATUS fill_grent(struct group *result, struct winbindd_gr *gr, return NSS_STATUS_TRYAGAIN; } - strlcpy((result->gr_mem)[i], name, strlen(name) + 1); + strcpy((result->gr_mem)[i], name); i++; } @@ -344,7 +324,8 @@ static int num_pw_cache; /* Current size of pwd cache */ /* Rewind "file pointer" to start of ntdom password database */ -_PUBLIC_ NSS_STATUS _nss_winbind_setpwent(void) +NSS_STATUS +_nss_winbind_setpwent(void) { NSS_STATUS ret; #ifdef DEBUG_NSS @@ -353,10 +334,10 @@ _PUBLIC_ NSS_STATUS _nss_winbind_setpwent(void) if (num_pw_cache > 0) { ndx_pw_cache = num_pw_cache = 0; - free_response(&getpwent_response); + winbindd_free_response(&getpwent_response); } - ret = winbindd_request(WINBINDD_SETPWENT, NULL, NULL); + ret = winbindd_request_response(WINBINDD_SETPWENT, NULL, NULL); #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: setpwent returns %s (%d)\n", getpid(), nss_err_str(ret), ret); @@ -366,7 +347,8 @@ _PUBLIC_ NSS_STATUS _nss_winbind_setpwent(void) /* Close ntdom password database "file pointer" */ -_PUBLIC_ NSS_STATUS _nss_winbind_endpwent(void) +NSS_STATUS +_nss_winbind_endpwent(void) { NSS_STATUS ret; #ifdef DEBUG_NSS @@ -375,10 +357,10 @@ _PUBLIC_ NSS_STATUS _nss_winbind_endpwent(void) if (num_pw_cache > 0) { ndx_pw_cache = num_pw_cache = 0; - free_response(&getpwent_response); + winbindd_free_response(&getpwent_response); } - ret = winbindd_request(WINBINDD_ENDPWENT, NULL, NULL); + ret = winbindd_request_response(WINBINDD_ENDPWENT, NULL, NULL); #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: endpwent returns %s (%d)\n", getpid(), nss_err_str(ret), ret); @@ -388,8 +370,9 @@ _PUBLIC_ NSS_STATUS _nss_winbind_endpwent(void) /* Fetch the next password entry from ntdom password database */ -_PUBLIC_ NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, - char *buffer, size_t buflen, int *errnop) +NSS_STATUS +_nss_winbind_getpwent_r(struct passwd *result, char *buffer, + size_t buflen, int *errnop) { NSS_STATUS ret; struct winbindd_request request; @@ -409,7 +392,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, /* Else call winbindd to get a bunch of entries */ if (num_pw_cache > 0) { - free_response(&getpwent_response); + winbindd_free_response(&getpwent_response); } ZERO_STRUCT(request); @@ -417,7 +400,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, request.data.num_entries = MAX_GETPWENT_USERS; - ret = winbindd_request(WINBINDD_GETPWENT, &request, + ret = winbindd_request_response(WINBINDD_GETPWENT, &request, &getpwent_response); if (ret == NSS_STATUS_SUCCESS) { @@ -448,20 +431,20 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, /* Out of memory - try again */ if (ret == NSS_STATUS_TRYAGAIN) { - called_again = True; + called_again = true; *errnop = errno = ERANGE; goto done; } *errnop = errno = 0; - called_again = False; + called_again = false; ndx_pw_cache++; /* If we've finished with this lot of results free cache */ if (ndx_pw_cache == num_pw_cache) { ndx_pw_cache = num_pw_cache = 0; - free_response(&getpwent_response); + winbindd_free_response(&getpwent_response); } } done: @@ -474,8 +457,9 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getpwent_r(struct passwd *result, /* Return passwd struct from uid */ -_PUBLIC_ NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, - char *buffer, size_t buflen, int *errnop) +NSS_STATUS +_nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, + size_t buflen, int *errnop) { NSS_STATUS ret; static struct winbindd_response response; @@ -496,14 +480,14 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, request.data.uid = uid; - ret = winbindd_request(WINBINDD_GETPWUID, &request, &response); + ret = winbindd_request_response(WINBINDD_GETPWUID, &request, &response); if (ret == NSS_STATUS_SUCCESS) { ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; + keep_response = true; *errnop = errno = ERANGE; goto done; } @@ -516,16 +500,16 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; + keep_response = true; *errnop = errno = ERANGE; goto done; } - keep_response = False; + keep_response = false; *errnop = errno = 0; } - free_response(&response); + winbindd_free_response(&response); done: #ifdef DEBUG_NSS @@ -536,8 +520,9 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getpwuid_r(uid_t uid, struct passwd *result, } /* Return passwd struct from username */ -_PUBLIC_ NSS_STATUS _nss_winbind_getpwnam_r(const char *name, - struct passwd *result, char *buffer, size_t buflen, int *errnop) +NSS_STATUS +_nss_winbind_getpwnam_r(const char *name, struct passwd *result, char *buffer, + size_t buflen, int *errnop) { NSS_STATUS ret; static struct winbindd_response response; @@ -562,14 +547,14 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getpwnam_r(const char *name, request.data.username [sizeof(request.data.username) - 1] = '\0'; - ret = winbindd_request(WINBINDD_GETPWNAM, &request, &response); + ret = winbindd_request_response(WINBINDD_GETPWNAM, &request, &response); if (ret == NSS_STATUS_SUCCESS) { ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; + keep_response = true; *errnop = errno = ERANGE; goto done; } @@ -582,16 +567,16 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getpwnam_r(const char *name, ret = fill_pwent(result, &response.data.pw, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; + keep_response = true; *errnop = errno = ERANGE; goto done; } - keep_response = False; + keep_response = false; *errnop = errno = 0; } - free_response(&response); + winbindd_free_response(&response); done: #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getpwnam %s returns %s (%d)\n", getpid(), @@ -611,7 +596,8 @@ static int num_gr_cache; /* Current size of grp cache */ /* Rewind "file pointer" to start of ntdom group database */ -_PUBLIC_ NSS_STATUS _nss_winbind_setgrent(void) +NSS_STATUS +_nss_winbind_setgrent(void) { NSS_STATUS ret; #ifdef DEBUG_NSS @@ -620,10 +606,10 @@ _PUBLIC_ NSS_STATUS _nss_winbind_setgrent(void) if (num_gr_cache > 0) { ndx_gr_cache = num_gr_cache = 0; - free_response(&getgrent_response); + winbindd_free_response(&getgrent_response); } - ret = winbindd_request(WINBINDD_SETGRENT, NULL, NULL); + ret = winbindd_request_response(WINBINDD_SETGRENT, NULL, NULL); #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: setgrent returns %s (%d)\n", getpid(), nss_err_str(ret), ret); @@ -633,7 +619,8 @@ _PUBLIC_ NSS_STATUS _nss_winbind_setgrent(void) /* Close "file pointer" for ntdom group database */ -_PUBLIC_ NSS_STATUS _nss_winbind_endgrent(void) +NSS_STATUS +_nss_winbind_endgrent(void) { NSS_STATUS ret; #ifdef DEBUG_NSS @@ -642,10 +629,10 @@ _PUBLIC_ NSS_STATUS _nss_winbind_endgrent(void) if (num_gr_cache > 0) { ndx_gr_cache = num_gr_cache = 0; - free_response(&getgrent_response); + winbindd_free_response(&getgrent_response); } - ret = winbindd_request(WINBINDD_ENDGRENT, NULL, NULL); + ret = winbindd_request_response(WINBINDD_ENDGRENT, NULL, NULL); #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: endgrent returns %s (%d)\n", getpid(), nss_err_str(ret), ret); @@ -679,7 +666,7 @@ winbind_getgrent(enum winbindd_cmd cmd, /* Else call winbindd to get a bunch of entries */ if (num_gr_cache > 0) { - free_response(&getgrent_response); + winbindd_free_response(&getgrent_response); } ZERO_STRUCT(request); @@ -687,7 +674,7 @@ winbind_getgrent(enum winbindd_cmd cmd, request.data.num_entries = MAX_GETGRENT_USERS; - ret = winbindd_request(cmd, &request, + ret = winbindd_request_response(cmd, &request, &getgrent_response); if (ret == NSS_STATUS_SUCCESS) { @@ -727,20 +714,20 @@ winbind_getgrent(enum winbindd_cmd cmd, /* Out of memory - try again */ if (ret == NSS_STATUS_TRYAGAIN) { - called_again = True; + called_again = true; *errnop = errno = ERANGE; goto done; } *errnop = 0; - called_again = False; + called_again = false; ndx_gr_cache++; /* If we've finished with this lot of results free cache */ if (ndx_gr_cache == num_gr_cache) { ndx_gr_cache = num_gr_cache = 0; - free_response(&getgrent_response); + winbindd_free_response(&getgrent_response); } } done: @@ -752,13 +739,15 @@ winbind_getgrent(enum winbindd_cmd cmd, } -_PUBLIC_ NSS_STATUS _nss_winbind_getgrent_r(struct group *result, +NSS_STATUS +_nss_winbind_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop) { return winbind_getgrent(WINBINDD_GETGRENT, result, buffer, buflen, errnop); } -_PUBLIC_ NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, +NSS_STATUS +_nss_winbind_getgrlst_r(struct group *result, char *buffer, size_t buflen, int *errnop) { return winbind_getgrent(WINBINDD_GETGRLST, result, buffer, buflen, errnop); @@ -766,7 +755,8 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getgrlst_r(struct group *result, /* Return group struct from group name */ -_PUBLIC_ NSS_STATUS _nss_winbind_getgrnam_r(const char *name, +NSS_STATUS +_nss_winbind_getgrnam_r(const char *name, struct group *result, char *buffer, size_t buflen, int *errnop) { @@ -793,7 +783,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getgrnam_r(const char *name, request.data.groupname [sizeof(request.data.groupname) - 1] = '\0'; - ret = winbindd_request(WINBINDD_GETGRNAM, &request, &response); + ret = winbindd_request_response(WINBINDD_GETGRNAM, &request, &response); if (ret == NSS_STATUS_SUCCESS) { ret = fill_grent(result, &response.data.gr, @@ -801,7 +791,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getgrnam_r(const char *name, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; + keep_response = true; *errnop = errno = ERANGE; goto done; } @@ -816,16 +806,16 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getgrnam_r(const char *name, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; + keep_response = true; *errnop = errno = ERANGE; goto done; } - keep_response = False; + keep_response = false; *errnop = 0; } - free_response(&response); + winbindd_free_response(&response); done: #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getgrnam %s returns %s (%d)\n", getpid(), @@ -836,7 +826,8 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getgrnam_r(const char *name, /* Return group struct from gid */ -_PUBLIC_ NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, +NSS_STATUS +_nss_winbind_getgrgid_r(gid_t gid, struct group *result, char *buffer, size_t buflen, int *errnop) { @@ -860,7 +851,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, request.data.gid = gid; - ret = winbindd_request(WINBINDD_GETGRGID, &request, &response); + ret = winbindd_request_response(WINBINDD_GETGRGID, &request, &response); if (ret == NSS_STATUS_SUCCESS) { @@ -869,7 +860,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, &buffer, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; + keep_response = true; *errnop = errno = ERANGE; goto done; } @@ -884,16 +875,16 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, &buflen); if (ret == NSS_STATUS_TRYAGAIN) { - keep_response = True; + keep_response = true; *errnop = errno = ERANGE; goto done; } - keep_response = False; + keep_response = false; *errnop = 0; } - free_response(&response); + winbindd_free_response(&response); done: #ifdef DEBUG_NSS fprintf(stderr, "[%5d]: getgrgid %d returns %s (%d)\n", getpid(), @@ -904,9 +895,10 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getgrgid_r(gid_t gid, /* Initialise supplementary groups */ -_PUBLIC_ NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, - long int *start, long int *size, gid_t **groups, - long int limit, int *errnop) +NSS_STATUS +_nss_winbind_initgroups_dyn(char *user, gid_t group, long int *start, + long int *size, gid_t **groups, long int limit, + int *errnop) { NSS_STATUS ret; struct winbindd_request request; @@ -924,7 +916,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, strncpy(request.data.username, user, sizeof(request.data.username) - 1); - ret = winbindd_request(WINBINDD_GETGROUPS, &request, &response); + ret = winbindd_request_response(WINBINDD_GETGROUPS, &request, &response); if (ret == NSS_STATUS_SUCCESS) { int num_gids = response.data.num_entries; @@ -1003,9 +995,10 @@ _PUBLIC_ NSS_STATUS _nss_winbind_initgroups_dyn(char *user, gid_t group, /* return a list of group SIDs for a user SID */ -_PUBLIC_ NSS_STATUS _nss_winbind_getusersids(const char *user_sid, - char **group_sids, int *num_groups, - char *buffer, size_t buf_size, int *errnop) +NSS_STATUS +_nss_winbind_getusersids(const char *user_sid, char **group_sids, + int *num_groups, + char *buffer, size_t buf_size, int *errnop) { NSS_STATUS ret; struct winbindd_request request; @@ -1021,7 +1014,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getusersids(const char *user_sid, strncpy(request.data.sid, user_sid,sizeof(request.data.sid) - 1); request.data.sid[sizeof(request.data.sid) - 1] = '\0'; - ret = winbindd_request(WINBINDD_GETUSERSIDS, &request, &response); + ret = winbindd_request_response(WINBINDD_GETUSERSIDS, &request, &response); if (ret != NSS_STATUS_SUCCESS) { goto done; @@ -1039,14 +1032,15 @@ _PUBLIC_ NSS_STATUS _nss_winbind_getusersids(const char *user_sid, errno = *errnop = 0; done: - free_response(&response); + winbindd_free_response(&response); return ret; } /* map a user or group name to a SID string */ -_PUBLIC_ NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, - char *buffer, size_t buflen, int *errnop) +NSS_STATUS +_nss_winbind_nametosid(const char *name, char **sid, char *buffer, + size_t buflen, int *errnop) { NSS_STATUS ret; struct winbindd_response response; @@ -1063,7 +1057,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, sizeof(request.data.name.name) - 1); request.data.name.name[sizeof(request.data.name.name) - 1] = '\0'; - ret = winbindd_request(WINBINDD_LOOKUPNAME, &request, &response); + ret = winbindd_request_response(WINBINDD_LOOKUPNAME, &request, &response); if (ret != NSS_STATUS_SUCCESS) { *errnop = errno = EINVAL; goto failed; @@ -1077,16 +1071,17 @@ _PUBLIC_ NSS_STATUS _nss_winbind_nametosid(const char *name, char **sid, *errnop = errno = 0; *sid = buffer; - strlcpy(*sid, response.data.sid.sid, strlen(response.data.sid.sid) + 1); + strcpy(*sid, response.data.sid.sid); failed: - free_response(&response); + winbindd_free_response(&response); return ret; } /* map a sid string to a user or group name */ -_PUBLIC_ NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, - char *buffer, size_t buflen, int *errnop) +NSS_STATUS +_nss_winbind_sidtoname(const char *sid, char **name, char *buffer, + size_t buflen, int *errnop) { NSS_STATUS ret; struct winbindd_response response; @@ -1103,14 +1098,14 @@ _PUBLIC_ NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, /* we need to fetch the separator first time through */ if (!sep_char) { - ret = winbindd_request(WINBINDD_INFO, &request, &response); + ret = winbindd_request_response(WINBINDD_INFO, &request, &response); if (ret != NSS_STATUS_SUCCESS) { *errnop = errno = EINVAL; goto failed; } sep_char = response.data.info.winbind_separator; - free_response(&response); + winbindd_free_response(&response); } @@ -1118,7 +1113,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, sizeof(request.data.sid) - 1); request.data.sid[sizeof(request.data.sid) - 1] = '\0'; - ret = winbindd_request(WINBINDD_LOOKUPSID, &request, &response); + ret = winbindd_request_response(WINBINDD_LOOKUPSID, &request, &response); if (ret != NSS_STATUS_SUCCESS) { *errnop = errno = EINVAL; goto failed; @@ -1143,13 +1138,13 @@ _PUBLIC_ NSS_STATUS _nss_winbind_sidtoname(const char *sid, char **name, *errnop = errno = 0; failed: - free_response(&response); + winbindd_free_response(&response); return ret; } /* map a sid to a uid */ -_PUBLIC_ NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, - int *errnop) +NSS_STATUS +_nss_winbind_sidtouid(const char *sid, uid_t *uid, int *errnop) { NSS_STATUS ret; struct winbindd_response response; @@ -1165,7 +1160,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_sidtouid(const char *sid, uid_t *uid, strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1); request.data.sid[sizeof(request.data.sid) - 1] = '\0'; - ret = winbindd_request(WINBINDD_SID_TO_UID, &request, &response); + ret = winbindd_request_response(WINBINDD_SID_TO_UID, &request, &response); if (ret != NSS_STATUS_SUCCESS) { *errnop = errno = EINVAL; goto failed; @@ -1178,8 +1173,8 @@ failed: } /* map a sid to a gid */ -_PUBLIC_ NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, - int *errnop) +NSS_STATUS +_nss_winbind_sidtogid(const char *sid, gid_t *gid, int *errnop) { NSS_STATUS ret; struct winbindd_response response; @@ -1195,7 +1190,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_sidtogid(const char *sid, gid_t *gid, strncpy(request.data.sid, sid, sizeof(request.data.sid) - 1); request.data.sid[sizeof(request.data.sid) - 1] = '\0'; - ret = winbindd_request(WINBINDD_SID_TO_GID, &request, &response); + ret = winbindd_request_response(WINBINDD_SID_TO_GID, &request, &response); if (ret != NSS_STATUS_SUCCESS) { *errnop = errno = EINVAL; goto failed; @@ -1208,7 +1203,8 @@ failed: } /* map a uid to a SID string */ -_PUBLIC_ NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, +NSS_STATUS +_nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, size_t buflen, int *errnop) { NSS_STATUS ret; @@ -1224,7 +1220,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, request.data.uid = uid; - ret = winbindd_request(WINBINDD_UID_TO_SID, &request, &response); + ret = winbindd_request_response(WINBINDD_UID_TO_SID, &request, &response); if (ret != NSS_STATUS_SUCCESS) { *errnop = errno = EINVAL; goto failed; @@ -1238,15 +1234,16 @@ _PUBLIC_ NSS_STATUS _nss_winbind_uidtosid(uid_t uid, char **sid, char *buffer, *errnop = errno = 0; *sid = buffer; - strlcpy(*sid, response.data.sid.sid, strlen(response.data.sid.sid) + 1); + strcpy(*sid, response.data.sid.sid); failed: - free_response(&response); + winbindd_free_response(&response); return ret; } /* map a gid to a SID string */ -_PUBLIC_ NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, +NSS_STATUS +_nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, size_t buflen, int *errnop) { NSS_STATUS ret; @@ -1262,7 +1259,7 @@ _PUBLIC_ NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, request.data.gid = gid; - ret = winbindd_request(WINBINDD_GID_TO_SID, &request, &response); + ret = winbindd_request_response(WINBINDD_GID_TO_SID, &request, &response); if (ret != NSS_STATUS_SUCCESS) { *errnop = errno = EINVAL; goto failed; @@ -1276,9 +1273,9 @@ _PUBLIC_ NSS_STATUS _nss_winbind_gidtosid(gid_t gid, char **sid, char *buffer, *errnop = errno = 0; *sid = buffer; - strlcpy(*sid, response.data.sid.sid, strlen(response.data.sid.sid) + 1); + strcpy(*sid, response.data.sid.sid); failed: - free_response(&response); + winbindd_free_response(&response); return ret; } -- cgit