1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1999 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/socket.h> 31 #include <netinet/in.h> 32 #include <arpa/inet.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <stdio.h> 36 #include <string.h> 37 #include <malloc.h> 38 #include <syslog.h> 39 #include <sys/tiuser.h> 40 41 #define ACCFILE "/var/yp/securenets" 42 #define MAXLINE 128 43 44 typedef union { 45 struct in_addr in4; 46 struct in6_addr in6; 47 } inaddr_t; 48 49 struct seclist { 50 sa_family_t af; 51 inaddr_t mask; 52 inaddr_t net; 53 struct seclist *next; 54 }; 55 56 static int string2inaddr(char *, sa_family_t *, inaddr_t *); 57 static int addrequal(sa_family_t af, inaddr_t *laddr, inaddr_t *mask, 58 inaddr_t *caddr); 59 60 static struct seclist *slist; 61 static int nofile = 0; 62 63 void 64 get_secure_nets(char *daemon_name) 65 { 66 FILE *fp; 67 char strung[MAXLINE], nmask[MAXLINE], net[MAXLINE]; 68 inaddr_t maskin, netin; 69 sa_family_t maskaf, netaf; 70 struct seclist *tmp1, *tmp2; 71 int items = 0, line = 0; 72 if (fp = fopen(ACCFILE, "r")) { 73 tmp1 = (struct seclist *) malloc(sizeof (struct seclist)); 74 slist = tmp2 = tmp1; 75 while (fgets(strung, MAXLINE, fp)) { 76 line++; 77 if (strung[strlen(strung) - 1] != '\n') { 78 syslog(LOG_ERR|LOG_DAEMON, 79 "%s: %s line %d: too long\n", 80 daemon_name, ACCFILE, line); 81 exit(1); 82 } 83 if (strung[0] != '#') { 84 items++; 85 if (sscanf(strung, 86 "%46s%46s", nmask, net) < 2) { 87 88 syslog(LOG_ERR|LOG_DAEMON, 89 "%s: %s line %d: missing fields\n", 90 daemon_name, ACCFILE, line); 91 exit(1); 92 } 93 netaf = AF_UNSPEC; 94 if (! string2inaddr(net, &netaf, &netin)) { 95 syslog(LOG_ERR|LOG_DAEMON, 96 "%s: %s line %d: error in address\n", 97 daemon_name, ACCFILE, line); 98 exit(1); 99 } 100 maskaf = netaf; 101 if (! string2inaddr(nmask, &maskaf, &maskin) || 102 maskaf != netaf) { 103 syslog(LOG_ERR|LOG_DAEMON, 104 "%s: %s line %d: error in netmask\n", 105 daemon_name, ACCFILE, line); 106 exit(1); 107 } 108 if (! addrequal(netaf, &netin, &maskin, 109 &netin)) { 110 syslog(LOG_ERR|LOG_DAEMON, 111 "%s: %s line %d: netmask does not match network\n", 112 daemon_name, ACCFILE, line); 113 exit(1); 114 } 115 116 tmp1->af = netaf; 117 tmp1->mask = maskin; 118 tmp1->net = netin; 119 tmp1->next = (struct seclist *) 120 malloc(sizeof (struct seclist)); 121 tmp2 = tmp1; 122 tmp1 = tmp1->next; 123 } 124 } 125 tmp2->next = NULL; 126 /* if nothing to process, set nofile flag and free up memory */ 127 if (items == 0) { 128 free(slist); 129 nofile = 1; 130 } 131 } else { 132 syslog(LOG_WARNING|LOG_DAEMON, "%s: no %s file\n", 133 daemon_name, ACCFILE); 134 nofile = 1; 135 } 136 } 137 138 int 139 check_secure_net_ti(struct netbuf *caller, char *ypname) { 140 struct seclist *tmp; 141 sa_family_t af; 142 inaddr_t addr; 143 char buf[INET6_ADDRSTRLEN]; 144 145 if (nofile) 146 return (1); 147 148 af = ((struct sockaddr_storage *)caller->buf)->ss_family; 149 if (af == AF_INET) { 150 addr.in4 = ((struct sockaddr_in *)caller->buf)->sin_addr; 151 } else if (af == AF_INET6) { 152 addr.in6 = ((struct sockaddr_in6 *)caller->buf)->sin6_addr; 153 } else { 154 return (1); 155 } 156 157 tmp = slist; 158 while (tmp != NULL) { 159 if (af == tmp->af && 160 addrequal(af, &tmp->net, &tmp->mask, &addr)) { 161 return (1); 162 } 163 tmp = tmp->next; 164 } 165 syslog(LOG_ERR|LOG_DAEMON, "%s: access denied for %s\n", 166 ypname, inet_ntop(af, 167 (af == AF_INET6) ? (void *)&addr.in6 : 168 (void *)&addr.in4, buf, sizeof (buf))); 169 170 return (0); 171 } 172 173 174 static int 175 string2inaddr(char *string, sa_family_t *af, inaddr_t *addr) { 176 177 sa_family_t stringaf = AF_UNSPEC; 178 179 stringaf = (strchr(string, ':') != 0) ? AF_INET6 : AF_INET; 180 181 if (*af != AF_UNSPEC && strcmp(string, "host") == 0) { 182 if (*af == AF_INET) { 183 string = "255.255.255.255"; 184 stringaf = AF_INET; 185 } else if (*af == AF_INET6) { 186 string = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; 187 stringaf = AF_INET6; 188 } 189 } 190 191 *af = stringaf; 192 if (inet_pton(*af, string, (*af == AF_INET6) ? (void *)&addr->in6 : 193 (void *)&addr->in4) != 1) { 194 return (0); 195 } 196 197 return (1); 198 } 199 200 201 static int 202 addrequal(sa_family_t af, inaddr_t *laddr, inaddr_t *mask, inaddr_t *caddr) { 203 204 if (af == AF_INET6) { 205 int i; 206 for (i = 0; i < sizeof (laddr->in6.s6_addr); i++) { 207 if ((caddr->in6.s6_addr[i] & mask->in6.s6_addr[i]) != 208 laddr->in6.s6_addr[i]) 209 return (0); 210 } 211 return (1); 212 } else if (af == AF_INET) { 213 return ((caddr->in4.s_addr & mask->in4.s_addr) == 214 laddr->in4.s_addr); 215 } else { 216 return (0); 217 } 218 } 219 220 221 static void 222 print_inaddr(char *string, sa_family_t af, inaddr_t *addr) { 223 224 char buf[INET6_ADDRSTRLEN]; 225 226 printf("%s %s %s\n", 227 string, (af == AF_INET6)?"AF_INET6":"AF_INET", 228 inet_ntop(af, (af == AF_INET6) ? (void *)&addr->in6 : 229 (void *)&addr->in4, buf, sizeof (buf))); 230 } 231