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
get_secure_nets(char * daemon_name)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
check_secure_net_ti(struct netbuf * caller,char * ypname)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
string2inaddr(char * string,sa_family_t * af,inaddr_t * addr)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
addrequal(sa_family_t af,inaddr_t * laddr,inaddr_t * mask,inaddr_t * caddr)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
print_inaddr(char * string,sa_family_t af,inaddr_t * addr)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