1/* 2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 3 * Portions Copyright(c) 1996, 1998 by Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18#if defined(LIBC_SCCS) && !defined(lint) 19static const char rcsid[] = "$Id: irp_gr.c,v 1.4 2005/04/27 04:56:27 sra Exp $"; 20#endif /* LIBC_SCCS and not lint */ 21 22/* extern */ 23 24#include "port_before.h" 25 26#ifndef WANT_IRS_PW 27static int __bind_irs_gr_unneeded; 28#else 29 30#include <syslog.h> 31#include <sys/param.h> 32#include <sys/types.h> 33 34#include <errno.h> 35#include <fcntl.h> 36#include <grp.h> 37#include <stdio.h> 38#include <stdlib.h> 39#include <string.h> 40#include <unistd.h> 41#include <syslog.h> 42 43#include <irs.h> 44#include <irp.h> 45#include <isc/memcluster.h> 46#include <isc/irpmarshall.h> 47 48#include "irs_p.h" 49#include "lcl_p.h" 50#include "irp_p.h" 51 52#include "port_after.h" 53 54 55/* Types. */ 56 57/*! \file 58 * \brief 59 * Module for the getnetgrent(3) family to use when connected to a 60 * remote irp daemon. 61 * \brief 62 * See irpd.c for justification of caching done here. 63 * 64 */ 65 66struct pvt { 67 struct irp_p *girpdata; /*%< global IRP data */ 68 int warned; 69 struct group group; 70}; 71 72/* Forward. */ 73 74static void gr_close(struct irs_gr *); 75static struct group * gr_next(struct irs_gr *); 76static struct group * gr_byname(struct irs_gr *, const char *); 77static struct group * gr_bygid(struct irs_gr *, gid_t); 78static void gr_rewind(struct irs_gr *); 79static void gr_minimize(struct irs_gr *); 80 81/* Private */ 82static void free_group(struct group *gr); 83 84 85/* Public. */ 86 87/*% 88 * Initialize the group sub-module. 89 * 90 */ 91 92struct irs_gr * 93irs_irp_gr(struct irs_acc *this) { 94 struct irs_gr *gr; 95 struct pvt *pvt; 96 97 if (!(gr = memget(sizeof *gr))) { 98 errno = ENOMEM; 99 return (NULL); 100 } 101 memset(gr, 0x0, sizeof *gr); 102 103 if (!(pvt = memget(sizeof *pvt))) { 104 memput(gr, sizeof *gr); 105 errno = ENOMEM; 106 return (NULL); 107 } 108 memset(pvt, 0x0, sizeof *pvt); 109 pvt->girpdata = this->private; 110 111 gr->private = pvt; 112 gr->close = gr_close; 113 gr->next = gr_next; 114 gr->byname = gr_byname; 115 gr->bygid = gr_bygid; 116 gr->rewind = gr_rewind; 117 gr->list = make_group_list; 118 gr->minimize = gr_minimize; 119 return (gr); 120} 121 122/* Methods. */ 123 124/*% 125 * Close the sub-module. 126 * 127 */ 128 129static void 130gr_close(struct irs_gr *this) { 131 struct pvt *pvt = (struct pvt *)this->private; 132 133 gr_minimize(this); 134 135 memput(pvt, sizeof *pvt); 136 memput(this, sizeof *this); 137} 138 139/*% 140 * Gets the next group out of the cached data and returns it. 141 * 142 */ 143 144static struct group * 145gr_next(struct irs_gr *this) { 146 struct pvt *pvt = (struct pvt *)this->private; 147 struct group *gr = &pvt->group; 148 char *body; 149 size_t bodylen; 150 int code; 151 char text[256]; 152 153 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { 154 return (NULL); 155 } 156 157 if (irs_irp_send_command(pvt->girpdata, "getgrent") != 0) { 158 return (NULL); 159 } 160 161 if (irs_irp_get_full_response(pvt->girpdata, &code, 162 text, sizeof text, 163 &body, &bodylen) != 0) { 164 if (irp_log_errors) { 165 syslog(LOG_WARNING, "getgrent failed: %s", text); 166 } 167 return (NULL); 168 } 169 170 if (code == IRPD_GETGROUP_OK) { 171 free_group(gr); 172 if (irp_unmarshall_gr(gr, body) != 0) { 173 gr = NULL; 174 } 175 } else { 176 gr = NULL; 177 } 178 179 if (body != NULL) { 180 memput(body, bodylen); 181 } 182 183 return (gr); 184} 185 186/*% 187 * Gets a group by name from irpd and returns it. 188 * 189 */ 190 191static struct group * 192gr_byname(struct irs_gr *this, const char *name) { 193 struct pvt *pvt = (struct pvt *)this->private; 194 struct group *gr = &pvt->group; 195 char *body; 196 size_t bodylen; 197 int code; 198 char text[256]; 199 200 201 if (gr->gr_name != NULL && strcmp(name, gr->gr_name) == 0) { 202 return (gr); 203 } 204 205 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { 206 return (NULL); 207 } 208 209 if (irs_irp_send_command(pvt->girpdata, "getgrnam %s", name) != 0) 210 return (NULL); 211 212 if (irs_irp_get_full_response(pvt->girpdata, &code, 213 text, sizeof text, 214 &body, &bodylen) != 0) { 215 return (NULL); 216 } 217 218 if (code == IRPD_GETGROUP_OK) { 219 free_group(gr); 220 if (irp_unmarshall_gr(gr, body) != 0) { 221 gr = NULL; 222 } 223 } else { 224 gr = NULL; 225 } 226 227 if (body != NULL) { 228 memput(body, bodylen); 229 } 230 231 return (gr); 232} 233 234/*% 235 * Gets a group by gid from irpd and returns it. 236 * 237 */ 238 239static struct group * 240gr_bygid(struct irs_gr *this, gid_t gid) { 241 struct pvt *pvt = (struct pvt *)this->private; 242 struct group *gr = &pvt->group; 243 char *body; 244 size_t bodylen; 245 int code; 246 char text[256]; 247 248 if (gr->gr_name != NULL && (gid_t)gr->gr_gid == gid) { 249 return (gr); 250 } 251 252 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { 253 return (NULL); 254 } 255 256 if (irs_irp_send_command(pvt->girpdata, "getgrgid %d", gid) != 0) 257 return (NULL); 258 259 if (irs_irp_get_full_response(pvt->girpdata, &code, 260 text, sizeof text, 261 &body, &bodylen) != 0) { 262 return (NULL); 263 } 264 265 if (code == IRPD_GETGROUP_OK) { 266 free_group(gr); 267 if (irp_unmarshall_gr(gr, body) != 0) { 268 gr = NULL; 269 } 270 } else { 271 gr = NULL; 272 } 273 274 if (body != NULL) { 275 memput(body, bodylen); 276 } 277 278 return (gr); 279} 280 281/*% 282 * void gr_rewind(struct irs_gr *this) 283 * 284 */ 285 286static void 287gr_rewind(struct irs_gr *this) { 288 struct pvt *pvt = (struct pvt *)this->private; 289 char text[256]; 290 int code; 291 292 if (irs_irp_connection_setup(pvt->girpdata, &pvt->warned) != 0) { 293 return; 294 } 295 296 if (irs_irp_send_command(pvt->girpdata, "setgrent") != 0) { 297 return; 298 } 299 300 code = irs_irp_read_response(pvt->girpdata, text, sizeof text); 301 if (code != IRPD_GETGROUP_SETOK) { 302 if (irp_log_errors) { 303 syslog(LOG_WARNING, "setgrent failed: %s", text); 304 } 305 } 306 307 return; 308} 309 310/*% 311 * Frees up cached data and disconnects(if necessary) from the remote. 312 * 313 */ 314 315static void 316gr_minimize(struct irs_gr *this) { 317 struct pvt *pvt = (struct pvt *)this->private; 318 319 free_group(&pvt->group); 320 irs_irp_disconnect(pvt->girpdata); 321} 322 323/* Private. */ 324 325/*% 326 * static void free_group(struct group *gr); 327 * 328 * Deallocate all the memory irp_unmarshall_gr allocated. 329 * 330 */ 331 332static void 333free_group(struct group *gr) { 334 char **p; 335 336 if (gr == NULL) 337 return; 338 339 if (gr->gr_name != NULL) 340 free(gr->gr_name); 341 342 if (gr->gr_passwd != NULL) 343 free(gr->gr_passwd); 344 345 for (p = gr->gr_mem ; p != NULL && *p != NULL ; p++) 346 free(*p); 347 348 if (gr->gr_mem) 349 free(gr->gr_mem); 350 351 if (p != NULL) 352 free(p); 353} 354 355 356#endif /* WANT_IRS_GR */ 357/*! \file */ 358