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 }