int do_shishi_login (int infd, struct auth_data *ad, const char **err_msg) { int rc; int error = 0; int keylen, keytype; struct passwd *pwd = NULL; int cksumtype, cksumlen = 30; char *cksum; char *compcksum; size_t compcksumlen; char cksumdata[100]; struct sockaddr_in sock; size_t socklen = sizeof (struct sockaddr_in); # ifdef ENCRYPTION rc = get_auth (infd, &ad->h, &ad->ap, &ad->enckey, err_msg, &ad->protocol, &cksumtype, &cksum, &cksumlen); # else rc = get_auth (infd, &ad->h, &ad->ap, NULL, err_msg, &ad->protocol, &cksumtype, &cksum, &cksumlen); # endif if (rc != SHISHI_OK) return rc; # ifdef ENCRYPTION /* init IV */ if (encrypt_io) { int i; char *iv; ad->ivtab[0] = &ad->iv1; ad->ivtab[1] = &ad->iv2; keytype = shishi_key_type (ad->enckey); keylen = shishi_cipher_blocksize (keytype); for (i = 0; i < 2; i++) { ad->ivtab[i]->ivlen = keylen; switch (keytype) { case SHISHI_DES_CBC_CRC: case SHISHI_DES_CBC_MD4: case SHISHI_DES_CBC_MD5: case SHISHI_DES_CBC_NONE: case SHISHI_DES3_CBC_HMAC_SHA1_KD: ad->ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES; ad->ivtab[i]->iv = malloc (ad->ivtab[i]->ivlen); memset (ad->ivtab[i]->iv, i, ad->ivtab[i]->ivlen); ad->ivtab[i]->ctx = shishi_crypto (ad->h, ad->enckey, ad->ivtab[i]->keyusage, shishi_key_type (ad->enckey), ad->ivtab[i]->iv, ad->ivtab[i]->ivlen); break; case SHISHI_ARCFOUR_HMAC: case SHISHI_ARCFOUR_HMAC_EXP: ad->ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 6 - 4 * i; ad->ivtab[i]->ctx = shishi_crypto (ad->h, ad->enckey, ad->ivtab[i]->keyusage, shishi_key_type (ad->enckey), NULL, 0); break; default: ad->ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 6 - 4 * i; ad->ivtab[i]->iv = malloc (ad->ivtab[i]->ivlen); memset (ad->ivtab[i]->iv, 0, ad->ivtab[i]->ivlen); if (ad->protocol == 2) ad->ivtab[i]->ctx = shishi_crypto (ad->h, ad->enckey, ad->ivtab[i]->keyusage, shishi_key_type (ad->enckey), ad->ivtab[i]->iv, ad->ivtab[i]->ivlen); } } } # endif getstr (infd, &ad->lusername, NULL); getstr (infd, &ad->term, "TERM="); getstr (infd, &ad->rusername, NULL); rc = read (infd, &error, sizeof (int)); if ((rc != sizeof (int)) && rc) { free (pwd); free (cksum); return 1; } /* getpwnam crash !!!! pwd = getpwnam (ad->lusername); if (pwd == NULL) { *err_msg = "getpwnam failed"; syslog (LOG_ERR, "getpwnam failed: %m"); return 1; } syslog (LOG_INFO | LOG_AUTH, "%sKerberos V login from %s on %s\n", (pwd->pw_uid == 0) ? "ROOT " : "", ad->lusername, ad->hostname); */ free (pwd); syslog (LOG_INFO | LOG_AUTH, "Kerberos V login from %s on %s\n", ad->lusername, ad->hostname); /* verify checksum */ if (getsockname (infd, (struct sockaddr *) &sock, &socklen) < 0) { syslog (LOG_ERR, "Can't get sock name"); fatal (infd, "Can't get sockname", 1); } snprintf (cksumdata, 100, "%u:%s%s", ntohs (sock.sin_port), ad->term + 5, ad->lusername); rc = shishi_checksum (ad->h, ad->enckey, 0, cksumtype, cksumdata, strlen (cksumdata), &compcksum, &compcksumlen); free (cksum); if (rc != SHISHI_OK || compcksumlen != cksumlen || memcmp (compcksum, cksum, cksumlen) != 0) { /* err_msg crash ? */ /* *err_msg = "checksum verify failed"; */ syslog (LOG_ERR, "checksum verify failed: %s", shishi_error (ad->h)); free (compcksum); return 1; } free (compcksum); rc = shishi_authorized_p (ad->h, shishi_ap_tkt (ad->ap), ad->lusername); if (!rc) { syslog (LOG_ERR, "User is not authorized to log in as: %s", ad->lusername); shishi_ap_done (ad->ap); return 1; } shishi_ap_done (ad->ap); return SHISHI_OK; }
int main (int argc, char **argv) { int index; struct passwd *pw; struct servent *sp; sigset_t sigs, osigs; int asrsh, rem; pid_t pid = 0; uid_t uid; char *args, *host; set_program_name (argv[0]); asrsh = 0; host = user = NULL; /* If called as something other than "rsh", use it as the host name */ { char *p = strrchr (argv[0], '/'); if (p) ++p; else p = argv[0]; if (strcmp (p, "rsh")) host = p; else asrsh = 1; } /* Parse command line */ iu_argp_init ("rsh", default_program_authors); argp_parse (&argp, argc, argv, ARGP_IN_ORDER, &index, NULL); if (index < argc) host = argv[index++]; /* To few args. */ if (!host) error (EXIT_FAILURE, 0, "host not specified"); /* If no further arguments, must have been called as rlogin. */ if (!argv[index]) { if (asrsh) *argv = (char *) "rlogin"; seteuid (getuid ()); setuid (getuid ()); execv (PATH_RLOGIN, argv); error (EXIT_FAILURE, errno, "cannot execute %s", PATH_RLOGIN); } argc -= index; argv += index; /* We must be setuid root. */ if (geteuid ()) error (EXIT_FAILURE, 0, "must be setuid root.\n"); if (!(pw = getpwuid (uid = getuid ()))) error (EXIT_FAILURE, 0, "unknown user id"); /* Accept user1@host format, though "-l user2" overrides user1 */ { char *p = strchr (host, '@'); if (p) { *p = '\0'; if (!user && p > host) user = host; host = p + 1; if (*host == '\0') error (EXIT_FAILURE, 0, "empty host name"); } } #if defined KERBEROS || defined SHISHI # ifdef ENCRYPTION /* -x turns off -n */ if (doencrypt) null_input_option = 0; # endif #endif args = copyargs (argv); sp = NULL; #ifdef KERBEROS if (use_kerberos) { sp = getservbyname ((doencrypt ? "ekshell" : "kshell"), "tcp"); if (sp == NULL) { use_kerberos = 0; warning ("can't get entry for %s/tcp service", doencrypt ? "ekshell" : "kshell"); } } #elif defined(SHISHI) if (use_kerberos) { sp = getservbyname ("kshell", "tcp"); if (sp == NULL) { use_kerberos = 0; warning ("can't get entry for %s/tcp service", "kshell"); } } #endif if (sp == NULL) sp = getservbyname ("shell", "tcp"); if (sp == NULL) error (EXIT_FAILURE, 0, "shell/tcp: unknown service"); #if defined KERBEROS || defined SHISHI try_connect: if (use_kerberos) { struct hostent *hp; /* fully qualify hostname (needed for krb_realmofhost) */ hp = gethostbyname (host); if (hp != NULL && !(host = strdup (hp->h_name))) error (EXIT_FAILURE, errno, "strdup"); # if defined KERBEROS rem = KSUCCESS; errno = 0; if (dest_realm == NULL) dest_realm = krb_realmofhost (host); # elif defined (SHISHI) rem = SHISHI_OK; errno = 0; # endif # ifdef ENCRYPTION if (doencrypt) # if defined SHISHI { int i; char *term; term = xmalloc (strlen (args) + 4); strcpy (term, "-x "); strcat (term, args); rem = krcmd_mutual (&h, &host, sp->s_port, &user, term, &rfd2, dest_realm, &enckey); if (rem > 0) { keytype = shishi_key_type (enckey); keylen = shishi_cipher_blocksize (keytype); ivtab[0] = &iv1; ivtab[1] = &iv2; ivtab[2] = &iv3; ivtab[3] = &iv4; for (i = 0; i < 4; i++) { ivtab[i]->ivlen = keylen; switch (keytype) { case SHISHI_DES_CBC_CRC: case SHISHI_DES_CBC_MD4: case SHISHI_DES_CBC_MD5: case SHISHI_DES_CBC_NONE: case SHISHI_DES3_CBC_HMAC_SHA1_KD: ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES; ivtab[i]->iv = malloc (ivtab[i]->ivlen); memset (ivtab[i]->iv, 2 * i + 1 * (i < 2) - 4 * (i >= 2), ivtab[i]->ivlen); ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), ivtab[i]->iv, ivtab[i]->ivlen); break; case SHISHI_ARCFOUR_HMAC: case SHISHI_ARCFOUR_HMAC_EXP: ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 2 + 4 * i; ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), NULL, 0); break; default: ivtab[i]->keyusage = SHISHI_KEYUSAGE_KCMD_DES + 2 + 4 * i; ivtab[i]->iv = malloc (ivtab[i]->ivlen); memset (ivtab[i]->iv, 0, ivtab[i]->ivlen); ivtab[i]->ctx = shishi_crypto (h, enckey, ivtab[i]->keyusage, shishi_key_type (enckey), ivtab[i]->iv, ivtab[i]->ivlen); } } } free (term); } else # else rem = krcmd_mutual (&host, sp->s_port, user, args, &rfd2, dest_realm, &cred, schedule); else # endif # endif rem = krcmd ( # if defined SHISHI &h, &host, sp->s_port, &user, args, &rfd2, dest_realm); # else &host, sp->s_port, user, args, &rfd2, dest_realm); # endif if (rem < 0) { use_kerberos = 0; sp = getservbyname ("shell", "tcp"); if (sp == NULL) error (EXIT_FAILURE, 0, "shell/tcp: unknown service"); if (errno == ECONNREFUSED) warning ("remote host doesn't support Kerberos"); if (errno == ENOENT) warning ("can't provide Kerberos auth data"); goto try_connect; } }