2 * helper.c - setuid helper program for authbind
4 * authbind is Copyright (C) 1998 Ian Jackson
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
34 # define CONFIGDIR "/etc/authbind"
37 static const char *rcsid="$Id$";
39 static void exiterrno(int e) {
40 exit(e>0 && e<128 ? e : ENOSYS);
43 static void perrorfail(const char *m) {
46 fprintf(stderr,"libauthbind's helper: %s: %s\n",m,strerror(e));
50 static void badusage(void) {
51 fprintf(stderr,"libauthbind's helper: bad usage\n (%s)\n",rcsid);
55 static struct sockaddr_in saddr;
57 static void authorised(void) {
58 if (bind(0,&saddr,sizeof(saddr))) exiterrno(errno);
62 int main(int argc, const char *const *argv) {
67 unsigned long addr, port, haddr, thaddr, thmask;
68 unsigned int hport, a1,a2,a3,a4, alen,pmin,pmax;
72 if (argc != 3) badusage();
73 addr= strtoul(argv[1],&ep,16); if (*ep || addr&~0x0ffffffffUL) badusage();
74 port= strtoul(argv[2],&ep,16); if (*ep || port&~0x0ffffUL) badusage();
76 if (hport >= IPPORT_RESERVED/2) _exit(EPERM);
78 if (chdir(CONFIGDIR)) perrorfail("chdir " CONFIGDIR);
80 fnbuf[sizeof(fnbuf)-1]= 0;
81 memset(&saddr,0,sizeof(saddr));
82 saddr.sin_family= AF_INET;
84 saddr.sin_addr.s_addr= addr;
86 snprintf(fnbuf,sizeof(fnbuf)-1,"byport/%u",hport);
87 if (!access(fnbuf,X_OK)) authorised();
88 if (errno != ENOENT) exiterrno(errno);
90 np= inet_ntoa(saddr.sin_addr); assert(np);
91 snprintf(fnbuf,sizeof(fnbuf)-1,"byaddr/%s:%u",np,hport);
92 if (!access(fnbuf,X_OK)) authorised();
93 if (errno != ENOENT) exiterrno(errno);
95 uid= getuid(); if (uid==(uid_t)-1) perrorfail("getuid");
96 snprintf(fnbuf,sizeof(fnbuf)-1,"byuid/%lu",(unsigned long)uid);
98 file= fopen(fnbuf,"r");
99 if (!file) exiterrno(errno==ENOENT ? EPERM : errno);
103 while (fgets(fnbuf,sizeof(fnbuf)-1,file)) {
105 sscanf(fnbuf," %u.%u.%u.%u/%u:%u,%u %n",
106 &a1,&a2,&a3,&a4,&alen,&pmin,&pmax,&nchar);
107 if (nchar != strlen(fnbuf) ||
108 alen>32 || pmin&~0x0ffff || pmax&~0x0ffff ||
109 a1&~0x0ff || a2&~0xff || a3&~0x0ff || a4&~0x0ff)
112 if (hport<pmin || hport>pmax) continue;
114 thaddr= (a1<<24)|(a2<<16)|(a3<<8)|(a4);
115 thmask= 0x0ffffffffUL<<(32-alen);
116 if ((haddr&thmask) != thaddr) continue;
119 if (ferror(file)) perrorfail("read per-uid file");