1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-23 17:34:34 +03:00

r15425: Use dynamic buffers in the IRIX nsswithch module to prevent truncation

of long group lists.
(This used to be commit d348d796c1)
This commit is contained in:
James Peach 2006-05-04 00:45:31 +00:00 committed by Gerald (Jerry) Carter
parent 4ab90ea08c
commit d2418fbf27

View File

@ -4,6 +4,7 @@
Windows NT Domain nsswitch module
Copyright (C) Tim Potter 2000
Copyright (C) James Peach 2006
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@ -23,8 +24,19 @@
#include "winbind_client.h"
#ifndef PRINTF_ATTRIBUTE
#define PRINTF_ATTRIBUTE(m, n)
#endif
#ifndef HAVE_ASPRINTF_DECL
/*PRINTFLIKE2 */
int asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3);
#endif
#ifdef HAVE_NS_API_H
#undef VOLATILE
#undef STATIC
#undef DYNAMIC
#include <ns_daemon.h>
#endif
@ -165,13 +177,10 @@ static int
winbind_callback(nsd_file_t **rqp, int fd)
{
struct winbindd_response response;
struct winbindd_pw *pw = &response.data.pw;
struct winbindd_gr *gr = &response.data.gr;
nsd_file_t *rq;
NSS_STATUS status;
fstring result;
char *members;
int i, maxlen;
char * result = NULL;
size_t rlen;
dequeue_request();
@ -192,76 +201,164 @@ winbind_callback(nsd_file_t **rqp, int fd)
nsd_logprintf(NSD_LOG_MIN,
"callback (winbind) returning not found, status = %d\n",
status);
rq->f_status = NS_NOTFOUND;
switch (status) {
case NSS_STATUS_UNAVAIL:
rq->f_status = NS_UNAVAIL;
break;
case NSS_STATUS_TRYAGAIN:
rq->f_status = NS_TRYAGAIN;
break;
case NSS_STATUS_NOTFOUND:
/* FALLTHRU */
default:
rq->f_status = NS_NOTFOUND;
}
return NSD_NEXT;
}
maxlen = sizeof(result) - 1;
switch ((int)rq->f_cmd_data) {
case WINBINDD_WINS_BYNAME:
case WINBINDD_WINS_BYIP:
snprintf(result,maxlen,"%s\n",response.data.winsresp);
break;
nsd_logprintf(NSD_LOG_MIN,
"callback (winbind) WINS_BYNAME | WINS_BYIP\n");
rlen = asprintf(&result, "%s\n", response.data.winsresp);
if (rlen == 0 || result == NULL) {
return NSD_ERROR;
}
free_response(&response);
nsd_logprintf(NSD_LOG_MIN, " %s\n", result);
nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC);
return NSD_OK;
case WINBINDD_GETPWUID:
case WINBINDD_GETPWNAM:
snprintf(result,maxlen,"%s:%s:%d:%d:%s:%s:%s\n",
pw->pw_name,
pw->pw_passwd,
pw->pw_uid,
pw->pw_gid,
pw->pw_gecos,
pw->pw_dir,
pw->pw_shell);
break;
{
struct winbindd_pw *pw = &response.data.pw;
nsd_logprintf(NSD_LOG_MIN,
"callback (winbind) GETPWUID | GETPWUID\n");
rlen = asprintf(&result,"%s:%s:%d:%d:%s:%s:%s\n",
pw->pw_name,
pw->pw_passwd,
pw->pw_uid,
pw->pw_gid,
pw->pw_gecos,
pw->pw_dir,
pw->pw_shell);
if (rlen == 0 || result == NULL)
return NSD_ERROR;
free_response(&response);
nsd_logprintf(NSD_LOG_MIN, " %s\n", result);
nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC);
return NSD_OK;
}
case WINBINDD_GETGRNAM:
case WINBINDD_GETGRGID:
if (gr->num_gr_mem && response.extra_data.data)
members = response.extra_data.data;
else
members = "";
snprintf(result,maxlen,"%s:%s:%d:%s\n",
gr->gr_name, gr->gr_passwd, gr->gr_gid, members);
break;
{
const struct winbindd_gr *gr = &response.data.gr;
const char * members;
nsd_logprintf(NSD_LOG_MIN,
"callback (winbind) GETGRNAM | GETGRGID\n");
if (gr->num_gr_mem && response.extra_data.data) {
members = response.extra_data.data;
} else {
members = "";
}
rlen = asprintf(&result, "%s:%s:%d:%s\n",
gr->gr_name, gr->gr_passwd, gr->gr_gid, members);
if (rlen == 0 || result == NULL)
return NSD_ERROR;
free_response(&response);
nsd_logprintf(NSD_LOG_MIN, " %s\n", result);
nsd_set_result(rq, NS_SUCCESS, result, rlen, DYNAMIC);
return NSD_OK;
}
case WINBINDD_SETGRENT:
case WINBINDD_SETPWENT:
nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - SETPWENT/SETGRENT\n");
nsd_logprintf(NSD_LOG_MIN,
"callback (winbind) SETGRENT | SETPWENT\n");
free_response(&response);
return(do_list(1,rq));
case WINBINDD_GETGRENT:
case WINBINDD_GETGRLST:
nsd_logprintf(NSD_LOG_MIN,
"callback (winbind) - %d GETGRENT responses\n",
response.data.num_entries);
if (response.data.num_entries) {
gr = (struct winbindd_gr *)response.extra_data.data;
if (! gr ) {
nsd_logprintf(NSD_LOG_MIN, " no extra_data.data\n");
free_response(&response);
return NSD_ERROR;
}
members = (char *)response.extra_data.data +
(response.data.num_entries * sizeof(struct winbindd_gr));
for (i = 0; i < response.data.num_entries; i++) {
snprintf(result,maxlen,"%s:%s:%d:%s\n",
gr->gr_name, gr->gr_passwd, gr->gr_gid,
&members[gr->gr_mem_ofs]);
nsd_logprintf(NSD_LOG_MIN, " GETGRENT %s\n",result);
nsd_append_element(rq,NS_SUCCESS,result,strlen(result));
gr++;
}
}
i = response.data.num_entries;
free_response(&response);
if (i < MAX_GETPWENT_USERS)
return(do_list(2,rq));
else
return(do_list(1,rq));
{
int entries;
nsd_logprintf(NSD_LOG_MIN,
"callback (winbind) GETGRENT | GETGRLIST %d responses\n",
response.data.num_entries);
if (response.data.num_entries) {
const struct winbindd_gr *gr = &response.data.gr;
const char * members;
fstring grp_name;
int i;
gr = (struct winbindd_gr *)response.extra_data.data;
if (! gr ) {
nsd_logprintf(NSD_LOG_MIN, " no extra_data\n");
free_response(&response);
return NSD_ERROR;
}
members = (char *)response.extra_data.data +
(response.data.num_entries * sizeof(struct winbindd_gr));
for (i = 0; i < response.data.num_entries; i++) {
snprintf(grp_name, sizeof(grp_name) - 1, "%s:%s:%d:",
gr->gr_name, gr->gr_passwd, gr->gr_gid);
nsd_append_element(rq, NS_SUCCESS, result, rlen);
nsd_append_result(rq, NS_SUCCESS,
&members[gr->gr_mem_ofs],
strlen(&members[gr->gr_mem_ofs]));
/* Don't log the whole list, because it might be
* _really_ long and we probably don't want to clobber
* the log with it.
*/
nsd_logprintf(NSD_LOG_MIN, " %s (...)\n", grp_name);
gr++;
}
}
entries = response.data.num_entries;
free_response(&response);
if (entries < MAX_GETPWENT_USERS)
return(do_list(2,rq));
else
return(do_list(1,rq));
}
case WINBINDD_GETPWENT:
nsd_logprintf(NSD_LOG_MIN,
"callback (winbind) - %d GETPWENT responses\n",
{
int entries;
nsd_logprintf(NSD_LOG_MIN,
"callback (winbind) GETPWENT %d responses\n",
response.data.num_entries);
if (response.data.num_entries) {
struct winbindd_pw *pw = &response.data.pw;
int i;
pw = (struct winbindd_pw *)response.extra_data.data;
if (! pw ) {
nsd_logprintf(NSD_LOG_MIN, " no extra_data\n");
@ -269,41 +366,46 @@ winbind_callback(nsd_file_t **rqp, int fd)
return NSD_ERROR;
}
for (i = 0; i < response.data.num_entries; i++) {
snprintf(result,maxlen,"%s:%s:%d:%d:%s:%s:%s",
pw->pw_name,
pw->pw_passwd,
pw->pw_uid,
pw->pw_gid,
pw->pw_gecos,
pw->pw_dir,
pw->pw_shell);
nsd_logprintf(NSD_LOG_MIN, " GETPWENT %s\n",result);
nsd_append_element(rq,NS_SUCCESS,result,strlen(result));
result = NULL;
rlen = asprintf(&result, "%s:%s:%d:%d:%s:%s:%s",
pw->pw_name,
pw->pw_passwd,
pw->pw_uid,
pw->pw_gid,
pw->pw_gecos,
pw->pw_dir,
pw->pw_shell);
if (rlen != 0 && result != NULL) {
nsd_logprintf(NSD_LOG_MIN, " %s\n",result);
nsd_append_element(rq, NS_SUCCESS, result, rlen);
free(result);
}
pw++;
}
}
i = response.data.num_entries;
entries = response.data.num_entries;
free_response(&response);
if (i < MAX_GETPWENT_USERS)
if (entries < MAX_GETPWENT_USERS)
return(do_list(2,rq));
else
return(do_list(1,rq));
}
case WINBINDD_ENDGRENT:
case WINBINDD_ENDPWENT:
nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - ENDPWENT/ENDGRENT\n");
nsd_append_element(rq,NS_SUCCESS,"\n",1);
nsd_logprintf(NSD_LOG_MIN, "callback (winbind) ENDGRENT | ENDPWENT\n");
nsd_append_element(rq, NS_SUCCESS, "\n", 1);
free_response(&response);
return NSD_NEXT;
default:
free_response(&response);
nsd_logprintf(NSD_LOG_MIN, "callback (winbind) - no valid command\n");
nsd_logprintf(NSD_LOG_MIN, "callback (winbind) invalid command %d\n", (int)rq->f_cmd_data);
return NSD_NEXT;
}
nsd_logprintf(NSD_LOG_MIN, "callback (winbind) %s\n", result);
/* free any extra data area in response structure */
free_response(&response);
nsd_set_result(rq,NS_SUCCESS,result,strlen(result),VOLATILE);
return NSD_OK;
}
static int
@ -349,14 +451,16 @@ send_next_request(nsd_file_t *rq, struct winbindd_request *request)
return NSD_NEXT;
}
nsd_logprintf(NSD_LOG_MIN, "send_next_request (winbind) %d to = %d\n",
nsd_logprintf(NSD_LOG_MIN,
"send_next_request (winbind) %d, timeout = %d sec\n",
rq->f_cmd_data, timeout);
status = winbindd_send_request((int)rq->f_cmd_data,request);
SAFE_FREE(request);
if (status != NSS_STATUS_SUCCESS) {
nsd_logprintf(NSD_LOG_MIN,
"send_next_request (winbind) error status = %d\n",status);
"send_next_request (winbind) error status = %d\n",
status);
rq->f_status = status;
return NSD_NEXT;
}