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; }
/* read encrypted data on socket */ int readenc (Shishi * h, int sock, char *buf, int *len, char *iv, int *ivlen, Shishi_key * enckey) { char *out; char *outbis; char *iv2; int rc; int val; int outlen; int dlen = 0, blocksize, enctype, hashsize; /* read size of message */ read (sock, &dlen, sizeof (int)); dlen = ntohl (dlen); /* if 0 put read size to 0 */ if (!dlen) { *len = dlen; return SHISHI_OK; } /* convert size to encryption size */ enctype = shishi_key_type (enckey); blocksize = shishi_cipher_blocksize (enctype); hashsize = shishi_checksum_cksumlen (shishi_cipher_defaultcksumtype (enctype)); dlen += blocksize - 1 + 4; if (shishi_key_type (enckey) != SHISHI_DES3_CBC_HMAC_SHA1_KD) dlen += hashsize; else dlen += blocksize; dlen /= blocksize; dlen *= blocksize; if (shishi_key_type (enckey) == SHISHI_DES3_CBC_HMAC_SHA1_KD) dlen += hashsize; /* read encrypted data */ outbis = malloc (dlen); if (outbis == NULL) { printf ("Malloc error!\n"); return 1; } rc = read (sock, outbis, dlen); if (rc != dlen) { printf ("Error during read socket\n"); return 1; } /* decrypt it */ rc = shishi_decrypt_ivupdate (h, enckey, 1026, iv, *ivlen, &iv2, ivlen, outbis, dlen, &out, &outlen); if (rc != SHISHI_OK) { printf ("decryption error\n"); return 1; } /* len = first 4 bytes of decrypted data */ *len = ntohl (*((int *) out)); /* update iv */ memcpy (iv, iv2, *ivlen); /* Temp patch to remove 5 unidentified bytes data from server */ memset (buf, 0, BUFLEN); if ((unsigned char) out[4] == 255) val = 5 + sizeof (int); else val = sizeof (int); /* copy decrypted data to output */ memcpy (buf, out + val, strlen (out + val)); free (out); free (outbis); 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; } }
/* read encrypted data on socket */ int readenc (Shishi * h, int sock, char *buf, int *len, shishi_ivector * iv, Shishi_key * enckey, int proto) { char *out; char *outbis; int rc; int val; int outlen; int dlen = 0, blocksize, enctype, hashsize; /* read size of message */ read (sock, &dlen, sizeof (int)); dlen = ntohl (dlen); /* if 0 put read size to 0 */ if (!dlen) { *len = dlen; return SHISHI_OK; } if (proto == 1) *len = dlen; /* convert size to encryption size */ enctype = shishi_key_type (enckey); blocksize = shishi_cipher_blocksize (enctype); hashsize = shishi_checksum_cksumlen (shishi_cipher_defaultcksumtype (enctype)); switch (enctype) { case SHISHI_AES128_CTS_HMAC_SHA1_96: case SHISHI_AES256_CTS_HMAC_SHA1_96: dlen += 4 + hashsize + blocksize; break; case SHISHI_ARCFOUR_HMAC: case SHISHI_ARCFOUR_HMAC_EXP: dlen += 4 + 8 + blocksize - 1; dlen /= blocksize; dlen *= blocksize; dlen += hashsize; break; case SHISHI_DES3_CBC_HMAC_SHA1_KD: dlen += 4 + 2 * blocksize - 1; dlen /= blocksize; dlen *= blocksize; dlen += hashsize; break; case SHISHI_DES_CBC_CRC: dlen += 2 * blocksize - 1; if (proto == 2) dlen += 4; dlen += hashsize; dlen /= blocksize; dlen *= blocksize; break; default: dlen += blocksize - 1; if (proto == 2) dlen += 4; dlen += hashsize; dlen /= blocksize; dlen *= blocksize; break; } /* read encrypted data */ outbis = malloc (dlen); if (outbis == NULL) { perror ("readenc()"); return 1; } rc = read (sock, outbis, dlen); if (rc != dlen) { fprintf (stderr, "Error during read socket\n"); free (outbis); return 1; } if (proto == 1) { rc = shishi_decrypt (h, enckey, iv->keyusage, outbis, dlen, &out, &outlen); if (rc != SHISHI_OK) { fprintf (stderr, "decryption error\n"); free (outbis); return 1; } val = 0; } else { rc = shishi_crypto_decrypt (iv->ctx, outbis, dlen, &out, &outlen); if (rc != SHISHI_OK) { fprintf (stderr, "decryption error\n"); free (outbis); return 1; } /* in KCMDV0.2 first 4 bytes of decrypted data = len of data */ *len = ntohl (*((int *) out)); val = sizeof (int); } memset (buf, 0, BUFLEN); /* copy decrypted data to output */ memcpy (buf, out + val, outlen - val); free (out); free (outbis); return SHISHI_OK; }