int main() { uint8_t index; uint8_t menulen; uint8_t button_pressed = UINT8_MAX - 1; uint16_t i; uint8_t pass_len; //Since we are waiting indefinitely for input from keyboard, //the watchdog is not applicable anymore //wdt_enable(WDTO_1S); // enable 1s watchdog timer init(); for (i = 0; i < sizeof(keyboard_report); i++) // clear report initially ((uchar *) &keyboard_report)[i] = 0; usbDeviceDisconnect(); // enforce re-enumeration for (i = 0; i < 250; i++) { // wait 500 ms //wdt_reset(); _delay_ms(2); } usbDeviceConnect(); // Enable interrupts after re-enumeration sei(); //Enable this to reinitialize passwords/EEPROM //eeprom_write_byte(0,0); pass_no = read_passwords(&passwords); index = 0; mode = MODE_MENU; menulen = MENU_LENGTH; while (1) { //wdt_reset(); // keep the watchdog happy usbPoll(); //Only display stuff if a button was pressed //(most likely something changed on the screen) if (button_pressed != UINT8_MAX) { lcd_clrscr(); if (mode == MODE_MENU) { strcpy_P(stringBuffer, (PGM_P) pgm_read_word(&(menu_items[index]))); lcd_puts(stringBuffer); } else { lcd_puts(passwords[index]); } } button_pressed = poll_buttons(); switch (button_pressed) { case MENU: //Get back to the main menu mode = MODE_MENU; index = 0; menulen = MENU_LENGTH; toggle_led(PB0); break; case CYCLE: //Prepare next item for display if (index < menulen - 1) { lcd_clrscr(); index++; } else { index = 0; } toggle_led(PB0); break; case SELECT: if (mode == MODE_MENU) { //We can add password directly from the MENU mode (main menu) if (index == MODE_ADD) { uint8_t pass_len; pass_len = input_password(); if (pass_len > 0) { stringBuffer[pass_len] = '\0'; passwords = realloc(passwords, (pass_no + 1) * sizeof(char*)); passwords[pass_no] = malloc(pass_len * sizeof(char)); strcpy(passwords[pass_no], stringBuffer); pass_no++; menulen = pass_no; write_passwords(pass_no, passwords); } //Get back to the MENU mode (main menu) mode = MODE_MENU; menulen = MENU_LENGTH; toggle_led(PB0); } else { //Enter the corresponding mode mode = index; index = 0; menulen = pass_no; } } else { //in SEND, REMOVE or CHANGE mode if (index < menulen) { switch (mode) { case MODE_SEND: //Send password to the PC strcpy(stringBuffer, passwords[index]); messagePtr = 0; messageState = STATE_SEND; //Stay in the SEND mode displaying the same password break; case MODE_REMOVE: //Remove password free(passwords[index]); for (i = index; i < pass_no - 1; i++) { passwords[i] = passwords[i + 1]; } pass_no--; passwords = realloc(passwords, pass_no * sizeof(char*)); write_passwords(pass_no, passwords); //Stay in the REMOVE mode, but display the first password index = 0; menulen = pass_no; break; case MODE_CHANGE: pass_len = input_password(); if (pass_len > 0) { stringBuffer[pass_len] = '\0'; passwords[index] = realloc(passwords[index], pass_len); strcpy(passwords[index], stringBuffer); write_passwords(pass_no, passwords); } //Stay in the CHANGE mode, but display the first password index = 0; toggle_led(PB0); break; } } } break; } // characters are sent when messageState == STATE_SEND if (usbInterruptIsReady() && messageState == STATE_SEND) { messageState = buildReport(); usbSetInterrupt((void *) &keyboard_report, sizeof(keyboard_report)); } } return 0; }
static int set_password(const char *forwho, const char *shadow, const char *remember) { struct passwd *pwd = NULL; int retval; char pass[MAXPASS + 1]; char towhat[MAXPASS + 1]; int npass = 0; /* we don't care about number format errors because the helper should be called internally only */ int doshadow = atoi(shadow); int nremember = atoi(remember); char *passwords[] = { pass, towhat }; /* read the password from stdin (a pipe from the pam_unix module) */ npass = read_passwords(STDIN_FILENO, 2, passwords); if (npass != 2) { /* is it a valid password? */ if (npass == 1) { helper_log_err(LOG_DEBUG, "no new password supplied"); memset(pass, '\0', MAXPASS); } else { helper_log_err(LOG_DEBUG, "no valid passwords supplied"); } return PAM_AUTHTOK_ERR; } if (lock_pwdf() != PAM_SUCCESS) return PAM_AUTHTOK_LOCK_BUSY; pwd = getpwnam(forwho); if (pwd == NULL) { retval = PAM_USER_UNKNOWN; goto done; } /* If real caller uid is not root we must verify that received old pass agrees with the current one. We always allow change from null pass. */ if (getuid()) { retval = helper_verify_password(forwho, pass, 1); if (retval != PAM_SUCCESS) { goto done; } } /* first, save old password */ if (save_old_password(forwho, pass, nremember)) { retval = PAM_AUTHTOK_ERR; goto done; } if (doshadow || is_pwd_shadowed(pwd)) { retval = unix_update_shadow(forwho, towhat); if (retval == PAM_SUCCESS) if (!is_pwd_shadowed(pwd)) retval = unix_update_passwd(forwho, "x"); } else { retval = unix_update_passwd(forwho, towhat); } done: memset(pass, '\0', MAXPASS); memset(towhat, '\0', MAXPASS); unlock_pwdf(); if (retval == PAM_SUCCESS) { return PAM_SUCCESS; } else { return PAM_AUTHTOK_ERR; } }
int main(int argc, char *argv[]) { char pass[MAXPASS + 1]; char *option; int npass, nullok; int blankpass = 0; int retval = PAM_AUTH_ERR; char *user; char *passwords[] = { pass }; /* * Catch or ignore as many signal as possible. */ setup_signals(); /* * we establish that this program is running with non-tty stdin. * this is to discourage casual use. It does *NOT* prevent an * intruder from repeatadly running this program to determine the * password of the current user (brute force attack, but one for * which the attacker must already have gained access to the user's * account). */ if (isatty(STDIN_FILENO) || argc != 3 ) { helper_log_err(LOG_NOTICE ,"inappropriate use of Unix helper binary [UID=%d]" ,getuid()); #ifdef HAVE_LIBAUDIT _audit_log(AUDIT_ANOM_EXEC, getuidname(getuid()), PAM_SYSTEM_ERR); #endif fprintf(stderr ,"This binary is not designed for running in this way\n" "-- the system administrator has been informed\n"); sleep(10); /* this should discourage/annoy the user */ return PAM_SYSTEM_ERR; } /* * Determine what the current user's name is. * We must thus skip the check if the real uid is 0. */ if (getuid() == 0) { user=argv[1]; } else { user = getuidname(getuid()); /* if the caller specifies the username, verify that user matches it */ if (strcmp(user, argv[1])) { user = argv[1]; /* no match -> permanently change to the real user and proceed */ if (setuid(getuid()) != 0) return PAM_AUTH_ERR; } } option=argv[2]; if (strcmp(option, "chkexpiry") == 0) /* Check account information from the shadow file */ return _check_expiry(argv[1]); /* read the nullok/nonull option */ else if (strcmp(option, "nullok") == 0) nullok = 1; else if (strcmp(option, "nonull") == 0) nullok = 0; else { #ifdef HAVE_LIBAUDIT _audit_log(AUDIT_ANOM_EXEC, getuidname(getuid()), PAM_SYSTEM_ERR); #endif return PAM_SYSTEM_ERR; } /* read the password from stdin (a pipe from the pam_unix module) */ npass = read_passwords(STDIN_FILENO, 1, passwords); if (npass != 1) { /* is it a valid password? */ helper_log_err(LOG_DEBUG, "no password supplied"); *pass = '******'; } if (*pass == '\0') { blankpass = 1; } retval = helper_verify_password(user, pass, nullok); memset(pass, '\0', MAXPASS); /* clear memory of the password */ /* return pass or fail */ if (retval != PAM_SUCCESS) { if (!nullok || !blankpass) { /* no need to log blank pass test */ #ifdef HAVE_LIBAUDIT if (getuid() != 0) _audit_log(AUDIT_USER_AUTH, user, PAM_AUTH_ERR); #endif helper_log_err(LOG_NOTICE, "password check failed for user (%s)", user); } return PAM_AUTH_ERR; } else { if (getuid() != 0) { #ifdef HAVE_LIBAUDIT return _audit_log(AUDIT_USER_AUTH, user, PAM_SUCCESS); #else return PAM_SUCCESS; #endif } return PAM_SUCCESS; } }