1/* $NetBSD: dns_gr.c,v 1.1.1.2 2012/09/09 16:07:52 christos Exp $ */ 2 3/* 4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (c) 1996-1999 by Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#if defined(LIBC_SCCS) && !defined(lint) 21static const char rcsid[] = "Id: dns_gr.c,v 1.4 2005/04/27 04:56:21 sra Exp "; 22#endif 23 24/*! \file 25 * \brief 26 * dns_gr.c --- this file contains the functions for accessing 27 * group information from Hesiod. 28 */ 29 30#include "port_before.h" 31 32#ifndef WANT_IRS_GR 33static int __bind_irs_gr_unneeded; 34#else 35 36#include <sys/param.h> 37#include <sys/types.h> 38 39#include <stdio.h> 40#include <stdlib.h> 41#include <string.h> 42#include <errno.h> 43#include <unistd.h> 44 45#include <sys/types.h> 46#include <netinet/in.h> 47#include <arpa/nameser.h> 48#include <resolv.h> 49 50#include <isc/memcluster.h> 51 52#include <irs.h> 53 54#include "port_after.h" 55 56#include "irs_p.h" 57#include "hesiod.h" 58#include "dns_p.h" 59 60/* Types. */ 61 62struct pvt { 63 /* 64 * This is our private accessor data. It has a shared hesiod context. 65 */ 66 struct dns_p * dns; 67 /* 68 * Need space to store the entries read from the group file. 69 * The members list also needs space per member, and the 70 * strings making up the user names must be allocated 71 * somewhere. Rather than doing lots of small allocations, 72 * we keep one buffer and resize it as needed. 73 */ 74 struct group group; 75 size_t nmemb; /*%< Malloc'd max index of gr_mem[]. */ 76 char * membuf; 77 size_t membufsize; 78}; 79 80/* Forward. */ 81 82static struct group * gr_next(struct irs_gr *); 83static struct group * gr_byname(struct irs_gr *, const char *); 84static struct group * gr_bygid(struct irs_gr *, gid_t); 85static void gr_rewind(struct irs_gr *); 86static void gr_close(struct irs_gr *); 87static int gr_list(struct irs_gr *, const char *, 88 gid_t, gid_t *, int *); 89static void gr_minimize(struct irs_gr *); 90static struct __res_state * gr_res_get(struct irs_gr *); 91static void gr_res_set(struct irs_gr *, 92 struct __res_state *, 93 void (*)(void *)); 94 95static struct group * get_hes_group(struct irs_gr *this, 96 const char *name, 97 const char *type); 98 99/* Public. */ 100 101struct irs_gr * 102irs_dns_gr(struct irs_acc *this) { 103 struct dns_p *dns = (struct dns_p *)this->private; 104 struct irs_gr *gr; 105 struct pvt *pvt; 106 107 if (!dns || !dns->hes_ctx) { 108 errno = ENODEV; 109 return (NULL); 110 } 111 if (!(pvt = memget(sizeof *pvt))) { 112 errno = ENOMEM; 113 return (NULL); 114 } 115 memset(pvt, 0, sizeof *pvt); 116 pvt->dns = dns; 117 if (!(gr = memget(sizeof *gr))) { 118 memput(pvt, sizeof *pvt); 119 errno = ENOMEM; 120 return (NULL); 121 } 122 memset(gr, 0x5e, sizeof *gr); 123 gr->private = pvt; 124 gr->next = gr_next; 125 gr->byname = gr_byname; 126 gr->bygid = gr_bygid; 127 gr->rewind = gr_rewind; 128 gr->close = gr_close; 129 gr->list = gr_list; 130 gr->minimize = gr_minimize; 131 gr->res_get = gr_res_get; 132 gr->res_set = gr_res_set; 133 return (gr); 134} 135 136/* methods */ 137 138static void 139gr_close(struct irs_gr *this) { 140 struct pvt *pvt = (struct pvt *)this->private; 141 142 if (pvt->group.gr_mem) 143 free(pvt->group.gr_mem); 144 if (pvt->membuf) 145 free(pvt->membuf); 146 memput(pvt, sizeof *pvt); 147 memput(this, sizeof *this); 148} 149 150static struct group * 151gr_next(struct irs_gr *this) { 152 153 UNUSED(this); 154 155 return (NULL); 156} 157 158static struct group * 159gr_byname(struct irs_gr *this, const char *name) { 160 return (get_hes_group(this, name, "group")); 161} 162 163static struct group * 164gr_bygid(struct irs_gr *this, gid_t gid) { 165 char name[32]; 166 167 sprintf(name, "%ld", (long)gid); 168 return (get_hes_group(this, name, "gid")); 169} 170 171static void 172gr_rewind(struct irs_gr *this) { 173 174 UNUSED(this); 175 176 /* NOOP */ 177} 178 179static int 180gr_list(struct irs_gr *this, const char *name, 181 gid_t basegid, gid_t *groups, int *ngroups) 182{ 183 UNUSED(this); 184 UNUSED(name); 185 UNUSED(basegid); 186 UNUSED(groups); 187 188 *ngroups = 0; 189 /* There's some way to do this in Hesiod. */ 190 return (-1); 191} 192 193static void 194gr_minimize(struct irs_gr *this) { 195 196 UNUSED(this); 197 /* NOOP */ 198} 199 200/* Private. */ 201 202static struct group * 203get_hes_group(struct irs_gr *this, const char *name, const char *type) { 204 struct pvt *pvt = (struct pvt *)this->private; 205 char **hes_list, *cp, **new; 206 size_t num_members = 0; 207 u_long t; 208 209 hes_list = hesiod_resolve(pvt->dns->hes_ctx, name, type); 210 if (!hes_list) 211 return (NULL); 212 213 /* 214 * Copy the returned hesiod string into storage space. 215 */ 216 if (pvt->membuf) 217 free(pvt->membuf); 218 pvt->membuf = strdup(*hes_list); 219 hesiod_free_list(pvt->dns->hes_ctx, hes_list); 220 221 cp = pvt->membuf; 222 pvt->group.gr_name = cp; 223 if (!(cp = strchr(cp, ':'))) 224 goto cleanup; 225 *cp++ = '\0'; 226 227 pvt->group.gr_passwd = cp; 228 if (!(cp = strchr(cp, ':'))) 229 goto cleanup; 230 *cp++ = '\0'; 231 232 errno = 0; 233 t = strtoul(cp, NULL, 10); 234 if (errno == ERANGE) 235 goto cleanup; 236 pvt->group.gr_gid = (gid_t) t; 237 if (!(cp = strchr(cp, ':'))) 238 goto cleanup; 239 cp++; 240 241 /* 242 * Parse the members out. 243 */ 244 while (*cp) { 245 if (num_members+1 >= pvt->nmemb || pvt->group.gr_mem == NULL) { 246 pvt->nmemb += 10; 247 new = realloc(pvt->group.gr_mem, 248 pvt->nmemb * sizeof(char *)); 249 if (new == NULL) 250 goto cleanup; 251 pvt->group.gr_mem = new; 252 } 253 pvt->group.gr_mem[num_members++] = cp; 254 if (!(cp = strchr(cp, ','))) 255 break; 256 *cp++ = '\0'; 257 } 258 if (!pvt->group.gr_mem) { 259 pvt->group.gr_mem = malloc(sizeof(char*)); 260 if (!pvt->group.gr_mem) 261 goto cleanup; 262 } 263 pvt->group.gr_mem[num_members] = NULL; 264 265 return (&pvt->group); 266 267 cleanup: 268 if (pvt->group.gr_mem) { 269 free(pvt->group.gr_mem); 270 pvt->group.gr_mem = NULL; 271 } 272 if (pvt->membuf) { 273 free(pvt->membuf); 274 pvt->membuf = NULL; 275 } 276 return (NULL); 277} 278 279static struct __res_state * 280gr_res_get(struct irs_gr *this) { 281 struct pvt *pvt = (struct pvt *)this->private; 282 struct dns_p *dns = pvt->dns; 283 284 return (__hesiod_res_get(dns->hes_ctx)); 285} 286 287static void 288gr_res_set(struct irs_gr *this, struct __res_state * res, 289 void (*free_res)(void *)) { 290 struct pvt *pvt = (struct pvt *)this->private; 291 struct dns_p *dns = pvt->dns; 292 293 __hesiod_res_set(dns->hes_ctx, res, free_res); 294} 295 296#endif /* WANT_IRS_GR */ 297