waffle

user and group backend daemon
git clone git://git.2f30.org/waffle
Log | Files | Refs | LICENSE

req.c (5410B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 #include <unistd.h>
      6 #include "waffle.h"
      7 
      8 int
      9 handle_req(int clifd)
     10 {
     11 	ssize_t n;
     12 	struct nscdreq req;
     13 	char key[NSCDMAXKEYLEN];
     14 
     15 	n = read(clifd, &req, sizeof(req));
     16 	if (n <= 0)
     17 		return -1;
     18 
     19 	if ((size_t)n != sizeof(req))
     20 		return -1;
     21 
     22 	if (req.version != NSCDVERSION)
     23 		return -1;
     24 
     25 	if (req.keylen < 0 || req.keylen > NSCDMAXKEYLEN)
     26 		return -1;
     27 
     28 	if (!req.keylen) {
     29 		key[0] = '\0';
     30 		return process_req(clifd, &req, key);
     31 	}
     32 
     33 	n = read(clifd, key, sizeof(key));
     34 	if (n <= 0)
     35 		return -1;
     36 
     37 	if (n != req.keylen)
     38 		return -1;
     39 
     40 	if (key[n - 1] != '\0')
     41 		return -1;
     42 
     43 	return process_req(clifd, &req, key);
     44 }
     45 
     46 static int
     47 replypw(int clifd, struct passwd *pw)
     48 {
     49 	struct nscdpasswd header;
     50 	char *buf;
     51 	size_t len, offset;
     52 	ssize_t n;
     53 
     54 	if (!pw) {
     55 		header.version = NSCDVERSION;
     56 		header.found = 0;
     57 		header.namelen =  0;
     58 		header.passwdlen = 0;
     59 		header.uid = -1;
     60 		header.gid = -1;
     61 		header.gecoslen = 0;
     62 		header.dirlen =  0;
     63 		header.shelllen = 0;
     64 
     65 		len = sizeof(header);
     66 		buf = malloc(len);
     67 		if (!buf)
     68 			return -1;
     69 
     70 		memcpy(buf, &header, sizeof(header));
     71 	} else {
     72 		header.version = NSCDVERSION;
     73 		header.found = 1;
     74 		header.namelen = pw->pw_name ? strlen(pw->pw_name) + 1 : 1;
     75 		header.passwdlen = pw->pw_passwd ? strlen(pw->pw_passwd) + 1 : 1;
     76 		header.uid = pw->pw_uid;
     77 		header.gid = pw->pw_gid;
     78 		header.gecoslen = pw->pw_gecos ? strlen(pw->pw_gecos) + 1 : 1;
     79 		header.dirlen = pw->pw_dir ? strlen(pw->pw_dir) + 1 : 1;
     80 		header.shelllen = pw->pw_shell ? strlen(pw->pw_shell) + 1 : 1;
     81 
     82 		len = sizeof(header) +
     83 		      header.namelen +
     84 		      header.passwdlen +
     85 		      header.gecoslen +
     86 		      header.dirlen +
     87 		      header.shelllen;
     88 
     89 		buf = malloc(len);
     90 		if (!buf)
     91 			return -1;
     92 
     93 		memcpy(buf, &header, sizeof(header));
     94 		offset = sizeof(header);
     95 
     96 		if (pw->pw_name)
     97 			memcpy(buf + offset, pw->pw_name, header.namelen);
     98 		else
     99 			buf[offset] = '\0';
    100 		offset += header.namelen;
    101 
    102 		if (pw->pw_passwd)
    103 			memcpy(buf + offset, pw->pw_passwd, header.passwdlen);
    104 		else
    105 			buf[offset] = '\0';
    106 		offset += header.passwdlen;
    107 
    108 		if (pw->pw_gecos)
    109 			memcpy(buf + offset, pw->pw_gecos, header.gecoslen);
    110 		else
    111 			buf[offset] = '\0';
    112 		offset += header.gecoslen;
    113 
    114 		if (pw->pw_dir)
    115 			memcpy(buf + offset, pw->pw_dir, header.dirlen);
    116 		else
    117 			buf[offset] = '\0';
    118 		offset += header.dirlen;
    119 
    120 		if (pw->pw_shell)
    121 			memcpy(buf + offset, pw->pw_shell, header.shelllen);
    122 		else
    123 			buf[offset] = '\0';
    124 	}
    125 
    126 	n = write(clifd, buf, len);
    127 	free(buf);
    128 	return (size_t)n != len ? -1 : 0;
    129 }
    130 
    131 static int
    132 replygr(int clifd, struct group *gr)
    133 {
    134 	struct nscdgrp header;
    135 	char *buf;
    136 	uint32_t *grlens;
    137 	size_t memsize = 0, len, offset;
    138 	ssize_t n;
    139 	int32_t i = 0;
    140 
    141 	if (!gr) {
    142 		header.version = NSCDVERSION;
    143 		header.found = 0;
    144 		header.namelen = 0;
    145 		header.passwdlen = 0;
    146 		header.gid = -1;
    147 		header.memcnt = 0;
    148 
    149 		len = sizeof(header);
    150 		buf = malloc(len);
    151 		if (!buf)
    152 			return -1;
    153 		memcpy(buf, &header, sizeof(header));
    154 	} else {
    155 		header.version = NSCDVERSION;
    156 		header.found = 1;
    157 		header.namelen = gr->gr_name ? strlen(gr->gr_name) + 1 : 1;
    158 		header.passwdlen = gr->gr_passwd ? strlen(gr->gr_passwd) + 1 : 1;
    159 		header.gid = gr->gr_gid;
    160 		if (gr->gr_mem)
    161 			for (i = 0; gr->gr_mem[i]; i++)
    162 				memsize += strlen(gr->gr_mem[i]) + 1;
    163 		header.memcnt = i;
    164 
    165 		len = sizeof(header) +
    166 		      header.namelen +
    167 		      header.passwdlen +
    168 		      header.memcnt * sizeof(uint32_t) +
    169 		      memsize;
    170 
    171 		buf = malloc(len);
    172 		if (!buf)
    173 			return -1;
    174 
    175 		memcpy(buf, &header, sizeof(header));
    176 		offset = sizeof(header);
    177 
    178 		grlens = (uint32_t *)&buf[offset];
    179 		for (i = 0; i < header.memcnt; i++)
    180 			grlens[i] = strlen(gr->gr_mem[i]) + 1;
    181 		offset += header.memcnt * sizeof(uint32_t);
    182 
    183 		if (gr->gr_name)
    184 			memcpy(buf + offset, gr->gr_name, header.namelen);
    185 		else
    186 			buf[offset] = '\0';
    187 		offset += header.namelen;
    188 
    189 		if (gr->gr_passwd)
    190 			memcpy(buf + offset, gr->gr_passwd, header.passwdlen);
    191 		else
    192 			buf[offset] = '\0';
    193 		offset += header.passwdlen;
    194 
    195 		for (i = 0; i < header.memcnt; i++) {
    196 			memcpy(buf + offset, gr->gr_mem[i],
    197 			       strlen(gr->gr_mem[i]) + 1);
    198 			offset += grlens[i];
    199 		}
    200 	}
    201 
    202 	n = write(clifd, buf, len);
    203 	free(buf);
    204 	return (size_t)n != len ? -1 : 0;
    205 }
    206 
    207 int
    208 process_req(int clifd, struct nscdreq *req, char *key)
    209 {
    210 	struct passwd pw;
    211 	struct group gr;
    212 	size_t i;
    213 	int r = -1;
    214 
    215 	pw.pw_name = NULL;
    216 	pw.pw_passwd = NULL;
    217 	pw.pw_uid = -1;
    218 	pw.pw_gid = -1;
    219 	pw.pw_gecos = NULL;
    220 	pw.pw_dir = NULL;
    221 	pw.pw_shell = NULL;
    222 
    223 	gr.gr_name = NULL;
    224 	gr.gr_passwd = NULL;
    225 	gr.gr_gid = -1;
    226 	gr.gr_mem = NULL;
    227 
    228 	switch (req->type) {
    229 	case GETPWBYNAME:
    230 		if (!backends_pwbyname(key, &pw))
    231 			r = replypw(clifd, &pw);
    232 		else
    233 			r = replypw(clifd, NULL);
    234 		break;
    235 	case GETPWBYUID:
    236 		if (!backends_pwbyuid(key, &pw))
    237 			r = replypw(clifd, &pw);
    238 		else
    239 			r = replypw(clifd, NULL);
    240 		break;
    241 	case GETGRBYNAME:
    242 		if (!backends_grbyname(key, &gr))
    243 			r = replygr(clifd, &gr);
    244 		else
    245 			r = replygr(clifd, NULL);
    246 		break;
    247 	case GETGRBYGID:
    248 		if (!backends_grbygid(key, &gr))
    249 			r = replygr(clifd, &gr);
    250 		else
    251 			r = replygr(clifd, NULL);
    252 		break;
    253 	}
    254 	free(pw.pw_name);
    255 	free(pw.pw_passwd);
    256 	free(pw.pw_gecos);
    257 	free(pw.pw_dir);
    258 	free(pw.pw_shell);
    259 	free(gr.gr_name);
    260 	free(gr.gr_passwd);
    261 	if (gr.gr_mem)
    262 		for (i = 0; gr.gr_mem[i]; i++)
    263 			free(gr.gr_mem[i]);
    264 	free(gr.gr_mem);
    265 	return r;
    266 }