示例#1
0
文件: rlogind.c 项目: Jactry/shishi
int main(int argc, char **argv) {
	struct sockaddr_storage peer_sa;
	struct sockaddr *peer = (struct sockaddr *)&peer_sa;
	int peerlen = sizeof(peer_sa);
	
	char user[1024];
	char luser[1024];
	char term[1024];
		
	int port;
	
	struct passwd *pw;
	
	int err;
	
	char opt;

	char host[NI_MAXHOST];
	
	char buf[4096];
	int len;
	
	struct pollfd pfd[3];
	
	struct winsize winsize;
	uint16_t winbuf[4];
	int i;
	
	int master, slave;
	char *tty;

	pam_handle_t *handle;		
	struct pam_conv conv = {conv_h, NULL};
	const void *item;
	char *pamuser;
	
	int pid;
	
	argv0 = argv[0];
	
	/* Process options */
			
	while((opt = getopt(argc, argv, "+")) != -1) {
		switch(opt) {
			default:
				syslog(LOG_ERR, "Unknown option!");
				usage();
				return 1;
		}
	}
	
	if(optind != argc) {
		syslog(LOG_ERR, "Too many arguments!");
		usage();
		return 1;
	}
	
	/* Check source of connection */
	
	if(getpeername(0, peer, &peerlen)) {
		syslog(LOG_ERR, "Can't get address of peer: %m");
		return 1;
	}
	
	/* Unmap V4MAPPED addresses */
	
	if(peer->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)peer)->sin6_addr)) {
		((struct sockaddr_in *)peer)->sin_addr.s_addr = ((struct sockaddr_in6 *)peer)->sin6_addr.s6_addr32[3];
		peer->sa_family = AF_INET;
	}

	/* Lookup hostname */
	
	if((err = getnameinfo(peer, peerlen, host, sizeof(host), NULL, 0, 0))) {
		syslog(LOG_ERR, "Error resolving address: %s", gai_strerror(err));
		return 1;
	}
	
	/* Check if connection comes from a privileged port */
	
	switch(peer->sa_family) {
		case AF_INET:
			port = ntohs(((struct sockaddr_in *)peer)->sin_port);
			break;
		case AF_INET6:
			port = ntohs(((struct sockaddr_in6 *)peer)->sin6_port);
			break;
		default:
			port = -1;
			break;
	}

	if(port != -1 && (port < 512 || port >= 1024)) {
		syslog(LOG_ERR, "Connection from %s on illegal port %d.", host, port);
		return 1;
	}
	
	/* Wait for NULL byte */
	
	if(read(0, buf, 1) != 1 || *buf) {
		syslog(LOG_ERR, "Didn't receive NULL byte from %s: %m\n", host);
		return 1;
	}

	/* Read usernames and terminal info */
	
	if(readtonull(0, user, sizeof(user)) <= 0 || readtonull(0, luser, sizeof(luser)) <= 0) {
		syslog(LOG_ERR, "Error while receiving usernames from %s: %m", host);
		return 1;
	}
	
	if(readtonull(0, term, sizeof(term)) <= 0) {
		syslog(LOG_ERR, "Error while receiving terminal from %s: %m", host);
		return 1;
	}
	
	syslog(LOG_NOTICE, "Connection from %s@%s for %s", user, host, luser);
	
	/* We need to have a pty before we can use PAM */
	
	if(openpty(&master, &slave, 0, 0, &winsize) != 0) {
		syslog(LOG_ERR, "Could not open pty: %m");
		return 1;
	}
	
	tty = ttyname(slave);

	/* Start PAM */
	
	if((err = pam_start("rlogin", luser, &conv, &handle)) != PAM_SUCCESS) {
		safewrite(1, "Authentication failure\n", 23);
		syslog(LOG_ERR, "PAM error: %s", pam_strerror(handle, err));
		return 1;
	}
		
	pam_set_item(handle, PAM_USER, luser);
	pam_set_item(handle, PAM_RUSER, user);
	pam_set_item(handle, PAM_RHOST, host);
	pam_set_item(handle, PAM_TTY, tty);

	/* Write NULL byte to client so we can give a login prompt if necessary */
	
	if(safewrite(1, "", 1) == -1) {
		syslog(LOG_ERR, "Unable to write NULL byte: %m");
		return 1;
	}
	
	/* Try to authenticate */
	
	err = pam_authenticate(handle, 0);
	
	/* PAM might ask for a new password */
	
	if(err == PAM_NEW_AUTHTOK_REQD) {
		err = pam_chauthtok(handle, PAM_CHANGE_EXPIRED_AUTHTOK);
		if(err == PAM_SUCCESS)
			err = pam_authenticate(handle, 0);
	}
	
	if(err != PAM_SUCCESS) {
		safewrite(1, "Authentication failure\n", 23);
		syslog(LOG_ERR, "PAM error: %s", pam_strerror(handle, err));
		return 1;
	}

	/* Check account */
	
	err = pam_acct_mgmt(handle, 0);
	
	if(err != PAM_SUCCESS) {
		safewrite(1, "Authentication failure\n", 23);
		syslog(LOG_ERR, "PAM error: %s", pam_strerror(handle, err));
		return 1;
	}

	/* PAM can map the user to a different user */
	
	err = pam_get_item(handle, PAM_USER, &item);
	
	if(err != PAM_SUCCESS) {
		syslog(LOG_ERR, "PAM error: %s", pam_strerror(handle, err));
		return 1;
	}
	
	pamuser = strdup((char *)item);
	
	if(!pamuser || !*pamuser) {
		syslog(LOG_ERR, "PAM didn't return a username?!");
		return 1;
	}

	pw = getpwnam(pamuser);

	if (!pw) {
		syslog(LOG_ERR, "PAM_USER does not exist?!");
		return 1;
	}
	
	if (setgid(pw->pw_gid)) {
		syslog(LOG_ERR, "setgid() failed: %m");
		return 1;
	}
	
	if (initgroups(pamuser, pw->pw_gid)) {
		syslog(LOG_ERR, "initgroups() failed: %m");
		return 1;
	}
	
	err = pam_setcred(handle, PAM_ESTABLISH_CRED);
	
	if(err != PAM_SUCCESS) {
		syslog(LOG_ERR, "PAM error: %s", pam_strerror(handle, err));
		return 1;
	}
	
	/* Authentication succeeded */
	
	pam_end(handle, PAM_SUCCESS);
	
	/* spawn login shell */
	
	if((pid = fork()) < 0) {
		syslog(LOG_ERR, "fork() failed: %m");
		return 1;
	}
	
	if(send(1, "\x80", 1, MSG_OOB) <= 0) {
		syslog(LOG_ERR, "Unable to write OOB \x80: %m");
		return 1;
	}
	
	if(pid) {
		/* Parent process, still the rlogin server */
		
		close(slave);

		/* Process input/output */

		pfd[0].fd = 0;
		pfd[0].events = POLLIN | POLLERR | POLLHUP;
		pfd[1].fd = master;
		pfd[1].events = POLLIN | POLLERR | POLLHUP;
		
		for(;;) {
			errno = 0;

			if(poll(pfd, 2, -1) == -1) {
				if(errno == EINTR)
					continue;
				break;
			}

			if(pfd[0].revents) {
				len = read(0, buf, sizeof(buf));
				if(len <= 0)
					break;

				/* Scan for control messages. Yes this is evil and should be done differently. */
				
				for(i = 0; i < len - 11;) {
					if(buf[i++] == (char)0xFF)
					if(buf[i++] == (char)0xFF)
					if(buf[i++] == 's')
					if(buf[i++] == 's') {
						memcpy(winbuf, buf + i, 8);
						winsize.ws_row = ntohs(winbuf[0]);
						winsize.ws_col = ntohs(winbuf[1]);
						winsize.ws_xpixel = ntohs(winbuf[2]);
						winsize.ws_ypixel = ntohs(winbuf[3]);
						if(ioctl(master, TIOCSWINSZ, &winsize) == -1)
							break;
						memcpy(buf + i - 4, buf + i + 8, len - i - 8);
						i -= 4;
						len -= 12;
					}
				}
				
				if(safewrite(master, buf, len) == -1)
					break;
				pfd[0].revents = 0;
			}

			if(pfd[1].revents) {
				len = read(master, buf, sizeof(buf));
				if(len <= 0) {
					errno = 0;
					break;
				}
				if(safewrite(1, buf, len) == -1)
					break;
				pfd[1].revents = 0;
			}
		}

		/* The end */
		
		if(errno) {
			syslog(LOG_NOTICE, "Closing connection with %s@%s: %m", user, host);
			return 1;
		} else {
			syslog(LOG_NOTICE, "Closing connection with %s@%s", user, host);
			return 0;
		}
		
		close(master);
	} else {
		/* Child process, will become the shell */
		
		char *speed;
		struct termios tios;
		char *envp[2];

		/* Prepare tty for login */

		close(master);
		if(login_tty(slave)) {
			syslog(LOG_ERR, "login_tty() failed: %m");
			return 1;
		}

		/* Fix terminal type and speed */
		
		tcgetattr(0, &tios);

		if((speed = strchr(term, '/'))) {
			*speed++ = '\0';
			cfsetispeed(&tios, atoi(speed));
			cfsetospeed(&tios, atoi(speed));
		}
		
		tcsetattr(0, TCSADRAIN, &tios);

		/* Create environment */

		asprintf(&envp[0], "TERM=%s", term);
		envp[1] = NULL;

		/* Spawn login process */
		
		execle("/bin/login", "login", "-p", "-h", host, "-f", pamuser, NULL, envp);

		syslog(LOG_ERR, "Failed to spawn login process: %m");
		return 1;
	}
}
示例#2
0
int main(int argc, char *argv[])
{
    int fd;
    char gpsdev[64] = "/dev/rfcomm0";
    //    char gpsdev[64] = "/dev/ttyUSB0";
    unsigned i;

    if( argc > 1 )
        strcpy( gpsdev, argv[1] );

    fd = open(gpsdev, O_RDWR);
    if (fd < 0)
        return -10;

    struct termios tio;
    if ((tcgetattr(fd, &tio)) == -1)
        return -1;
    cfmakeraw(&tio);
    if ((tcsetattr(fd, TCSAFLUSH, &tio)) == -1)
        return -1;
    // add: find baud rate

    unsigned char *ephdata;
    long ephbytes;

    ephdata = ephbuf;
    int ofd = open("Eph.dat", O_RDONLY);
    if (ofd < 0)
        return -2;
    ephbytes = read(ofd, ephbuf, 256 * 1024);
    if (ephbytes < 65536)
        return -3;

    // checksum
    unsigned char csuma, csumb = 0;
    for (i = 0; i < 0x10000; i++)
        csumb += ephdata[i];
    csuma = csumb;
    for (; i < ephbytes; i++)
        csuma += ephdata[i];

   // AGPS download startup: send command, get ack - maybe put in loop?
    do {
	printf( "Startup\n" );
        do { // flush input buffer
            i = read(fd, string, 256);
        } while( i == 256 );
        write(fd, setagps, 8);
        i = 0;
	string[0] = 0;
	int cnt=0;
        while ( i < 0 || string[0] != '\xa0') {
            i = read(fd, string, 1);
	    cnt += i;
	    if( cnt > 5000 )
		continue;
	}
	printf( "Response\n" );
        while (i < 256) {
            i += read(fd, &string[i], 256 - i); // read extra junk after the response, sometimes partial sentence queued and going out.
            if (i > 8 && string[8] == 0x0a)
                break;
        }
    } while( memcmp(&string[i - 9], agpsresp, 9) );
    printf( "Venus Ready\n" );
    
    usleep(500000);  // wait for switch into AGPS mode - this is required.
    /* start the transmission */
    sprintf(string, "BINSIZE = %ld Checksum = %d Checksumb = %d ", ephbytes, csuma, csumb);
    write(fd, string, strlen(string) + 1);
    printf("%s\n", string);
    readtonull(fd);

#define BLKSIZ 8192
    unsigned tot = ephbytes;
    while (ephbytes > 0) {
        printf("%ld%% ", (tot - ephbytes) * 100 / tot);

        write(fd, ephdata, ephbytes > BLKSIZ ? BLKSIZ : ephbytes);
	readtonull(fd);        // OK or Error, null terminated
        ephbytes -= BLKSIZ;
        ephdata += BLKSIZ;
    }
    // Status "END" or "Error2"
    readtonull(fd);            // END
    //    readtonull(fd);            // END
    printf( "Finish and emable\n");
    sleep(1);
    write(fd, agpsena, 9);
    // maybe get ack?
    sleep(1);
    close(fd);
    return 0;
}
示例#3
0
文件: agpsup.c 项目: tz1/minigpsd
int main(int argc, char *argv[])
{
    int fd;
    //    char gpsdev[64] = "/dev/rfcomm0";
    char gpsdev[64] = "/dev/ttyUSB0";
    unsigned i;

    if( argc > 1 )
        strcpy( gpsdev, argv[1] );

    fd = open(gpsdev, O_RDWR);
    if (fd < 0)
        return -10;

    struct termios tio;
    if ((tcgetattr(fd, &tio)) == -1)
        return -1;
    cfmakeraw(&tio);
    if ((tcsetattr(fd, TCSAFLUSH, &tio)) == -1)
        return -1;
    // add: find baud rate

    unsigned char *ephdata;
    long ephbytes;

    ephdata = ephbuf;
    int ofd = open("Eph.dat", O_RDONLY);
    if (ofd < 0)
        return -2;
    ephbytes = read(ofd, ephbuf, 256 * 1024);
    if (ephbytes < 65536)
        return -3;

    // checksum
    unsigned char csuma, csumb = 0;
    for (i = 0; i < 0x10000; i++)
        csumb += ephdata[i];
    csuma = csumb;
    for (; i < ephbytes; i++)
        csuma += ephdata[i];

    // AGPS download startup: send command, get ack - maybe put in loop?
    printf( "Startup\n" );
    do {
        do { // flush input buffer
            i = read(fd, string, 64);
        } while( i == 64 );
        write(fd, setagps, 8);
        i = 0;
        while ( i < 0 || string[0] != '\xa0')
            i = read(fd, string, 1);
        while (i < 64) {
            i += read(fd, &string[i], 64 - i);
            if (i > 0 && string[i-1] == 0x0a)
                break;
        }
    } while( memcmp(&string[i - 9], agpsresp, 9) );
    printf( "Venus Ready\n" );
    
    /* start the transmission */
    sprintf(string, "BINSIZE = %ld Checksum = %d Checksumb = %d ", ephbytes, csuma, csumb);
    printf("%s:", string);
    write(fd, string, strlen(string) + 1);
    readtonull(fd);

#define BLKSIZ 8192
    while (ephbytes > 0) {
        printf("%ld left:", ephbytes);
        write(fd, ephdata, ephbytes > BLKSIZ ? BLKSIZ : ephbytes);
        readtonull(fd);        // OK
        ephbytes -= BLKSIZ;
        ephdata += BLKSIZ;
    }
    // Status "END" or "Error2"
    readtonull(fd);            // END

    sleep(1);
    write(fd, agpsena, 9);
    // maybe get ack?
    sleep(1);
    close(fd);
    return 0;
}