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; } }
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; }
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; }