⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 deslogind.c

📁 一个使用des加密传输的unix下的login程序的服务器端和客户端
💻 C
📖 第 1 页 / 共 4 页
字号:
      }   }   while ((ch = getopt(argc, argv, "w:k:Pl:t:i:f:p:dvnc")) != EOF) switch (ch) {   case 'c': 				   /* user compile'd userFile key */      userPhrase = (char *) -1;      break;   case 'k': 				   /* user file cipher key */      userPhrase = optarg;      break;   case 'n': 				   /* no user file cipher key */      noUserKey++;      break;   case 'P':      pty = 0;				   /* pipeline instead of pty */      break;   case 'l':      logName = optarg;      break;   case 'i':					/* idle timeout */      count = sscanf(optarg, "%u", &connTimeout);	/* in seconds */      if (count != 1) goto usage;      connTimeout *= 1000;      break;   case 't':					/* passphrase timeout */      count = sscanf(optarg, "%u", &loginTimeout);	/* in seconds */      if (count != 1) goto usage;      loginTimeout *= 1000;      break;   case 'f':					/* set userfile */      userFile = optarg;      break;   case 'p':					/* bind to port # */      count = sscanf(optarg, "%u", &port);      if (count != 1) goto usage;      break;   case 'w':				/* function as wrapper for login */      generic = optarg;	 /* name in userfile with system-wide passphrase */      break;   case 'v':      verbose++;      break;   case 'd':      debug++;      break;   default:usage:	log("usage: %s  [-dn] [-w name ] [-i inactiveSecs ] [-t loginSecs ] [-l logfile ] [-f userfile ] [-k userfileCipherKey ] [-p port ]\n", progName);      return 1;   }   argc -= optind;   argv += optind;   if (debug > 1) {      log("%s: issocket(0) returned %d\n", progName, stype);   }   userKey = getUserFileKey(userFile, userPhrase, noUserKey);   if (userKey == (keyType) -1) {      return 1;   }   /*    * Open log *after* options parsed and some simple error checking,    * and *before* closing fd's 0,1, and 2.    */   res = openLog(logName);		/* leaves existing log if failed */   if (res < 0) {       log("%s: couldn't open logfile \"%s\"--%s\n", progName, logName, ERRMSG);      return 1;   }   setProgName();   res = handleSignals();		/* handle quit attempts */   if (res < 0) {      return 1;   }   /*    * The remote host name is not trustworthy for several reasons.    * We don't use it (or the remote IP address) for authentication.    * Relying on the Domain Name System, or the remote IP address    * is not something I'm willing to trust.  Here, we use it strictly    * for logging, and informational purposes (who, RHOSTNAME, etc).    */   if (getRemoteAddr(0, rhostName, sizeof rhostName, &rport) == 0) {      nfd = 0; 			/* From inetd.  0 and 1 is our socket. */      close(2);		/* inetd leaves it open */   } else {			/* Interactive invocation */      if (port == 0) {	 port = getServicePort(SERVICE_NAME);	 if ((int) port < 0) {	    port = DESLOGIN_PORT;	    log(	 "%s: WARNING--no \"%s\" service; using port %u\n", 	       progName, SERVICE_NAME, port);	 }      }      log("%s: Starting daemon pid %ld port %d\n", 	 progName, (unsigned long) getpid(), port);      /*        * Must close fds 0,1, and 2 *before* openServer and becomeDaemon       */      close(0);      close(1);      close(2);      pid = becomeDaemon();      if (pid < 0) {	 return 1;		/* messages already logged */      }      nfd = openServer(port, rhostName, sizeof rhostName, &rport, (debug < 2));      if (nfd < 0) {	 log("%s: open network port %d failed--%s\n", progName, port, ERRMSG);	 return 1;      }      setProgName(); /* Openserver did a fork when it returned successfully */      /*       * Openserver handed us nfd as fd 1, 0 is now available       */   }   log("%s: connect %s:%d\n", progName, rhostName, rport);   protocol = serverHandshake(nfd, rhostName, rport, SETUP_TIMEOUT);   if (!protocol) {      return 1;		/* log already done */   }   count = getString(nfd, ruser, USERNAME_SIZE-1, SETUP_TIMEOUT);   if (count == 0) {      log("%s: NORUSER  %s:%d\n", progName, rhostName, rport);      return 1;   }   count = getString(nfd, userName, USERNAME_SIZE-1, SETUP_TIMEOUT);   if (count == 0) {      log("%s: NOLUSER  %s@%s:%d\n", 	 progName, ruser, rhostName, rport);      return 1;   }   /*    * Minimize the the time the phrase must me visible in memory.    */   if (generic) {      chp = generic;   } else {      chp = userName;   }   res = getUserPhrase(userFile, passPhrase, PHRASE_SIZE, chp, userKey);   if (res == 0) {      log("%s: NOPHRASE %s@%s:%d->\"%s\"\n", 	 progName, ruser, rhostName, rport, chp);      return 1;   }   if (res == -1) {      log("%s: cannot open \"%s\" for user database\n", progName, userFile);      return 1;   }   if (res == -2) {      log("%s: incorrect decryption key for user database \"%s\"\n", 	 progName, userFile);      return 1;   }   key = challenge(nfd, passPhrase, loginTimeout);   if (key == (keyType) 0) {      log("%s: BADLOGIN %s@%s:%d->\"%s\"\n", 	 progName, ruser, rhostName, rport, userName);      return 1;   }   memset(passPhrase, '\0', PHRASE_SIZE);   if (!generic) {      res = getUserInfo(userName, &shell, &cwd, &uid, &gid);      if (res < 0) {	 log("%s: NOUSER   %s@%s:%d->\"%s\"\n",	    progName, ruser, rhostName, rport, userName);	 return 1;      }   } else {      shell = loginProg;      cwd   = loginCwd;		/* not used except for log message */      uid   = getuid();		/* cannot fail */      gid   = getgid();		/* cannot fail */   }   /*    * If /etc/nologin exists, just copy it to the port and terminate.    */#if defined(NOLOGIN_FILE)   res = open(NOLOGIN_FILE, O_RDONLY, 0);   if (res >= 0) {      log("%s: NOLOGIN %s@%s:%d->%s\n",	 progName, ruser, rhostName, rport, userName);      cipherCopy(nfd, res, 2, key);	  /* two seconds max to blast it out */      close(res);      exit(1);   }#endif   /*    * We really should log the tty assigned, and pid of the shell as well    */   log("%s: Login %s@%s:%d as %s(%u:%u) %s %s\n",      progName, ruser, rhostName, rport, userName, uid, gid, cwd, shell);   time(&loginTime);   if (pty) {      /*       * We only need to do all this pty stuff and forking, if we want       * the local process to use a the slave tty interface.  This will        * not always be the case.  We should add a feature to eliminate it       * for remote commands that do not need a tty as stdin, stdout & stderr.       *       * The openPty below make the slave the controlling terminal for       * this process, unless we use O_NOCTTY.       */      masterpty = 	 openPty(O_RDWR | O_NOCTTY, sname, mname, PTY_NAMESIZE, &slavepty);      if (masterpty < 0) {	 log("%s: no pty's available\n", progName);	 exit(1);      }      /*       * Better make sure this close relinquishes the slavepty as the        * controlling terminal if it was.  Otherwise, the child will be unable        * to reacquire it as the controlling terminal and exit.       *       * DEC Ultrix 4.3 definitely ignores O_NOCTTY, but this code makes       * sure that is harmless by closing the slave before the fork below.       *       * In fact, I can't figure out a way to force Ultrix to give me       * a controlling terminal.  It claims I got one, but then when I        * try to relinquish it, it fails ENOTTY.  tcgetpgrp is really busted       * on this machine.       */      pid_res = tcgetpgrp(slavepty);      if (debug > 1) {	 log("%s: tcgetpgrp(%d) returned pid %d\n", 	    progName, slavepty, pid_res);      }      if (debug && (pid_res >= (pid_t) 0)) {	 log("%s: WARNING--%s fd %d is controlling terminal of daemon!\n",	    progName, sname, slavepty);	 res = mkCtrlTty(slavepty, 0);	 if (debug > 1) {	    log("%s: mkCtrlTty(%d) returned %d\n", progName, slavepty, res);	 }	 if (res < 0) {	    log("%s: WARNING--couldn't relinquish control terminal--%s\n", 	        progName, ERRMSG);	 }      }      close(slavepty);      /*       * The next three calls can fail when running as a normal user       */      res = chmod(sname, TTY_MODE);      if (res < 0) {	 log("%s: WARNING--chmod(\"%s\",0%o) failed--%s\n",	    progName, sname, TTY_MODE, ERRMSG);      }      res = chown(sname, uid, gid);      if  (res < 0) {	 log("%s: WARNING--chown(\"%s\",%d,%d) failed--%s\n", 	    progName, sname, uid, gid, ERRMSG);      }      if (debug) {	 log("%s: \"%s\" %d->%d \"%s\"\n", 	    progName, mname, masterpty, slavepty, sname);      }   } else {			/* pipe */      /*       * We must make sure these are not fd's 0, 1, or 2, so this first       * call is just to use them up if necessary.       */      res = pipe(pipe2);      if (res < 0) {	 log("%s: pipe failed--%s\n", progName, ERRMSG);	 exit(1);      }      res = pipe(pipe1);      if (res < 0) {	 log("%s: pipe failed--%s\n", progName, ERRMSG);	 exit(1);      }      res = pipe(pipe0);      if (res < 0) {	 log("%s: pipe failed--%s\n", progName, ERRMSG);	 exit(1);      }      close(pipe2[0]);      close(pipe2[1]);      if (debug) {	 log("%s: pipe (%d>%d) (%d<%d)\n", progName,	    pipe0[1], pipe0[1], pipe1[0], pipe1[1]);      }   }   /*    * POSIX states default is not to receive signal when child dies (or stops)    * We want to know when it happens.  We must do this before the fork    * to prevent a race condition.  We must catch this signal to force    * the select call in txfr to interrupt when the child dies.  Note thhat    * this may do nothing if on systems where sysconf(_SC_JOB_CONTROL)     * returns 0 (although System V may implement SIGCHLD as SIGCLD.).  We'll    * just have to assume that this will allow us to detect when the child    * dies.  If not, the symptom is that exiting the remote shell will just    * hang until the INACTIVITY_TIMEOUT (connTimeout) expires.    */   chp = (char *) posignal(SIGCHLD, sigHandler);   if (chp == (char *) SIG_ERR) {      log("%s: sigaction SIGCHLD failed--%s\n", progName, ERRMSG);      return 1;   }   /*    * This fork is necessary to reset much of the process state and    * to ensure that setsid won't fail because we're a process group leader    * It is also needed to transport data from the pty to the socket     * (or control terminal) from the remote shell.    *    * Sect3:15: fork() ensures that child pid != any active pgid     */   pid = fork();   if (pid != 0) {			/* parent */      if (pid < 0) {			/* fork failure */	 log("%s: fork failed--%s\n", progName, ERRMSG);	 exit(1);      }      setProgName();      if (debug) {	 log("%s: parent pid %d; child pid %ld\n", 	     progName, getpid(), (long) pid);      }      if (pty) {	 /*	  * This must be done after we have a pty, and before we do a setuid.	  * It updates the utmp file so getlogin and who will work corretly.	  * It should be done only by the parent.	  * It's required on hp-ux even for -w (wrapper) option.	  */	 res = setlogin(sname, userName, rhostName, 0);	 if (res < 0) {	    log("%s: WARNING--setlogin %s to %s@%s failed--%s\n", 	       progName, sname, userName, rhostName, ERRMSG);	 }	 res = atexit(eraselogin);	 if (res < 0) {	    log("%s: WARNING--atexit of eraselogin failed--%s\n", 	    progName, ERRMSG);	 }	 /*	  * There is a race condition between the parent and the child.	  * On DEC, if the parent executes txfr before the child opens the	  * slave, we'll abort with an I/O error.  Wait until pty is ready.	  */	 res = waitReady(masterpty, buf, 1, SETUP_TIMEOUT);	 if (debug > 1) {	    log("%s: waitReady(%d,%u)=%d\n", 		progName, masterpty, SETUP_TIMEOUT, res);	 }	 if (res <= 0) {	    if (res < 0 && errno != EINTR) {	/* fail, and not SIGCHLD */	       log("%s: master pty handshake failed--%s\n", 		  progName, res, ERRMSG);	    } else if (res == 0) {	       log("%s: master pty handshake failed\n", progName, res);	    }	 } else {	    if (debug) {	       log("%s: txfr %d-decrypt->%d\n", progName, nfd, masterpty);	    }	    res = txfr(nfd, masterpty, masterpty, bufSize, connTimeout, key);	 }      } else {		/* pipe */	 close(pipe0[1]);	 close(pipe1[0]);	 if (debug) {	    log("%s: txfr pipe %d->%d<-%d\n", 	       progName, pipe0[0], nfd, pipe1[1]);	 }	 res = txfr(nfd, pipe0[0], pipe1[1], bufSize, connTimeout, key);      }      /*       * Really should be registered with atexit, but since it's just       * a session key anyway, it's not insecure to let's its carcass       * rot in inaccessible bits of free space.       */      destroyKey(&key);      /*       * Reap all terminated children so we don't leave zombie processes       * and make sure our child CPU times are updated.  Waitpid returns       * -1 when all children have been reaped, and 0 if still have        * unterminated children.       */      do {	 pid = waitpid(-1, &chldStat, WNOHANG);	 if (debug) {	    log("%s: waitpid returned %ld\n", progName, (long) pid);	 }      } while (pid > 0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -