#define PATH_PATH "/bin:/usr/bin:/usr/ucb" #define PATH_TMP "/tmp" #define PATH_SH "/bin/sh" #define NEWS_OWNER "news" /* ** Open the privileged port, then exec dnews. */ #include #include #include #include #include #include #if defined(NEED_TIME) #include #endif #include #include #include #include /* dnews_start gid uid port */ char *getconfig(char *s); int main(int argc, char *argv[]) { gid_t gid; uid_t uid; char buff[400],pflag[200]; struct sockaddr_in server; int on,i,j; static char **args; static char **env; int nntp_port = 119; struct stat sb; static char ddir[200],dpath[200]; char *p; sprintf(ddir,"%s/dnews",getconfig("config")); sprintf(dpath,"%s",getconfig("config")); printf("ddir = %s \n",ddir); openlog("dnews_start", LOG_DAEMON, LOG_DAEMON); if (stat(dpath, &sb) < 0 || !S_ISDIR(sb.st_mode)) { syslog(LOG_ERR, "DNEWS cant stat %s %m", dpath); perror("stat failed \n"); exit(1); } uid = sb.st_uid; gid = sb.st_gid; /* Create a socket and name it. */ if ((i = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_ERR,"DNEWS_start socket %m"); perror("socket failed \n"); exit(1); } on = 1; if (setsockopt(i, SOL_SOCKET, SO_REUSEADDR, (caddr_t)&on, sizeof on) < 0) syslog(LOG_ERR, "dnews cant setsockopt %m"); memset(&server, 0, sizeof server); server.sin_port = htons(nntp_port); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(i, (struct sockaddr *)&server, sizeof server) < 0) { syslog(LOG_ERR, "DNEWS_start cant bind %m"); perror("bind failed \n"); exit(1); } sprintf(pflag, "-p%d", i); /* Build the new argument vector. */ args = malloc(sizeof(char *)*argc+5); env = malloc(sizeof(char *)*10); j = 0; args[j++] = ddir; args[j++] = pflag; for (i = 1; argv[i]; ) args[j++] = argv[i++]; args[j] = NULL; setgid(gid); if (getgid() != gid) syslog(LOG_ERR, "DNEWS cant setgid to %d %m", gid); setuid(uid); if (getuid() != uid) syslog(LOG_ERR, "DNEWS cant setuid to %d %m", uid); printf("Set uid=%d gid=%d based on %s \n",uid,gid,dpath); sprintf(buff, "PATH=%s", PATH_PATH); env[1] = strdup(buff); sprintf(buff, "TMPDIR=%s", PATH_TMP); env[1] = strdup(buff); sprintf(buff, "SHELL=%s", PATH_SH); env[2] = strdup(buff); sprintf(buff, "LOGNAME=%s", NEWS_OWNER); env[3] = strdup(buff); sprintf(buff, "USER=%s", NEWS_OWNER); env[4] = strdup(buff); sprintf(buff, "HOME=%s", dpath); env[5] = strdup(buff); i = 6; if ((p = getenv("TZ")) != NULL) { sprintf(buff, "TZ=%s", p); env[i++] = strdup(buff); } env[i++] = NULL; printf("Exec {%s} \n",args[0]); execve(args[0], args, env); syslog(LOG_ERR, "dnews_start cant exec %s %m", args[0]); perror("Exec failed \n"); exit(1); } char *getconfig(char *name) { char bf[500]; char *s; FILE *f; f = fopen("/etc/dnews.conf","r"); if (f==NULL) { perror("Can't open /etc/dnews.conf \n"); return "dmy";} for (;!feof(f);) { fgets(bf,100,f); s = strtok(bf," \t\n"); if (s!=NULL) if (strcmp(s,name)==0) { s = strtok(NULL," \t\n"); if (s!=NULL) return s; } } return "dmy"; }