📄 login.c
字号:
/* login.c -- Magic C++ user verify program (Mostly) portable public-domain implementation -- Copyright(C) 2003 Magicunix Infomation Technology Limited This file is part of magicd. magicd is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. For details, see the Magic C++ World-Wide-Web page, `http://www.magicunix.com', or send a mail to the Magic C++ developers <support@magicunix.com>. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <signal.h>#include <termios.h>#include <sys/ioctl.h> /* 44BSD requires this too */#include <unistd.h>#ifdef HAVE_STROPTS_H#include <stropts.h>#endif#include <errno.h>#include <setjmp.h>#define _XOPEN_SOURCE#include <unistd.h>#ifdef HAVE_SHADOW_H#include <shadow.h>#endif#include "tcp.h"#include "login.h"#include "tools.h"#include "writetmp.h"#include "telnet.h"extern int debug; /*from magicd.c*/static jmp_buf timejmp;void time_jump(int n){ (void) longjmp(timejmp, 1);}void ttintest(int n ){ util_log("SIGTTIN received!\n");}/* This is the login/password authentication routine *//*self-verify , szNoRootUsername/szNoRootPasswd is user-defined username/passwd*/struct passwd * login_auth(fd,clientip, szNoRootUsername,szNoRootPasswd)int fd; /* The socket r/w file descriptor */char *clientip;char *szNoRootUsername;char *szNoRootPasswd;{ int noentry=1; /* No authorization yet */ int tries=RETRIES; /* The number of retries */ char login[BUFSIZ]; /* The login name */ char pass[BUFSIZ]; /* The password */ char *passptr; /* The encrypted passwd */ char *ptr; /* Miscellaneous pointer */ struct passwd *pw;#ifdef HAVE_SHADOW_H struct spwd *spw; /* The shadow structure */#endif struct stat sb; /* That generic stat structure */#ifdef WELCOME /* Print out the welcome message */ write(fd, WELCOME, strlen(WELCOME));#endif if ( setjmp(timejmp) ) { /* We are returming from a timeout alarm */ sprintf(login, "Login timed out after %d seconds\r\n", TIMEOUT); write(fd, login, strlen(login)); return NULL; } signal(SIGALRM, time_jump); alarm(TIMEOUT); while ( noentry && tries ) { write(fd, LOGINOUTPUT, strlen(LOGINOUTPUT)); if ( get_line(fd, login, BUFSIZ, 1,clientip) == NULL ) break; if ( strlen(login) == 0 ) continue; --tries; /* * You can replace getpwnam() with any routine that takes * a login name and returns a struct passwd for that login, * or NULL for a nonexistent login name. */ if ( strcmp(login,szNoRootUsername) != 0 ) { write(fd, "Password: ", 10); get_line(fd, pass, BUFSIZ, 0,clientip); ptr="Login incorrect\r\n"; util_log("User: %s login failed!",login); write(fd, ptr, strlen(ptr)); continue; } write(fd, "Password: ", 10); get_line(fd, pass, BUFSIZ, 0 ,clientip); if ( strcmp(pass, szNoRootPasswd) == 0 ) { util_log("Password check OK...\n"); goto logit; } else { ptr="Login incorrect\r\n"; util_log("User: %s login failed!",login); write(fd, ptr, strlen(ptr)); } } alarm(0); /* Reset timeout alarm */ return NULL;logit: alarm(0); /* Reset timeout alarm */ util_log("User %s login success!\n",login); pw = getpwuid(getuid()); return pw;}/* This is a function to get a line of input, emulating line driver *//* \010 is the octal representation of Ctrl-H. */#define BS "\010 \010"#define CTRL_H 8 /* Decimal value of ^H (backspace key) */#define CTRL_U 21 /* Decimal value of ^U */#define CTRL_D 4 /* Decimal value of ^D */#define DEL 127 /* Decimal value of ^? (delete key) */static int at_cr=0; /* At a carriage return? */char *get_line(fd, buf, len, echo,clientip)int fd;char buf[];int len;int echo; /* Do we echo the input? */char *clientip;{ int i=0, newline=0; extern int telnet; /* From tcpserv.c */ extern int istelnet; /* From telnet.c */ struct Buf_Len buflen, *newbuflen; /* From tcp.h */ while ( !newline && ((buflen.len=read(fd, buflen.buffer, 1)) == 1) ) { if ( telnet ) { newbuflen=negotiate(fd, &buflen,clientip); } else newbuflen=(&buflen); /* Has the telnet negotiation used the input? */ if ( newbuflen->len == 0 ) continue; switch (newbuflen->buffer[0]) { case CTRL_H: /* Backspace */ case DEL: if ( echo && i ) write(fd, BS, 3); i -= (i ? 1 : 0); break; case CTRL_U: if ( echo ) { while ( i-- > 0 ) write(fd, BS, 3); } i=0; break; case '\r': at_cr=1; write(fd, "\r\n", 2); newline=1; break; case '\0': if ( at_cr ) at_cr=0; break; case '\n': if ( ! at_cr ) { write(fd, "\r\n", 2); newline=1; } else at_cr=0; break; case CTRL_D: if ( i == 0 ) return(NULL); default: if ( echo ) write(fd, newbuflen->buffer, 1); if ( i < len ) { buf[i++]=newbuflen->buffer[0]; } break; } } /*MC term send username +\r\n ,tty program send username+\r\0*/ /*magic frontend just send \r,so , can not read it anymore*/ if ( telnet ) { /*Read NUL or NL for CR-NUL or CR-NL sequence */ read(fd, buflen.buffer, 1); if ( (*buflen.buffer != '\0') && (*buflen.buffer != '\n') ) { buf[i++]=buflen.buffer[0]; } } if ( buflen.len <= 0 ) return(NULL); buf[i]='\0'; return(buf);} /* This function executes a shell, utilizing some login(1) standards. The home directory and shell are assumed to have been checked to make sure they exist. */extern int login;int login_exec(args, pw)char *args[];struct passwd *pw;{ extern char **environ; extern int errno; extern char remotehost[]; /* From tcpserv.c */ char path[BUFSIZ], argv0[BUFSIZ], *ptr; time_t now; FILE *fp; struct stat sb; /* The environment variables */ extern char **environ; struct winsize size; int nrow = 0; int ncol = 0; /* Set the nethost, no matter what happens */ if( debug ) util_log("Enter login_exec\n"); /*signal( SIGTTIN , ttintest );*/ /* If there is no login entry, don't perform login */ if ( ! pw ) { if( debug ) util_log("pw=0\n",args[0] ); if( login == 0 ) {#ifdef HAVE_UTMPX_H pututmpx();#endif } /*setup environment*/ else { clear_env(); set_the_env(pw); } if( debug ) util_log("exec = %s \n",args[0] ); return(execvp(args[0], args)); } /* Set the first argument of the program */ if ( args[ 0 ] ) { strcpy(argv0, args[ 0 ]); } /*using default shell of that user*/ else { args[ 1 ]=NULL; if ( *pw->pw_shell ) strcpy(argv0, pw->pw_shell); else strcpy(argv0, "/bin/sh"); } if ( (ptr=(char *)strrchr(argv0, '/')) == NULL ) { util_err_log( "Login shell is not a full pathname.", __FILE__, __LINE__,errno); return(-1); } ++ptr; if ( (args[0]=(char *)malloc(strlen(ptr)+2)) == NULL) { util_err_log( "malloc error.", __FILE__, __LINE__,errno); return(-1); } /*sprintf(args[0], "-%s", ptr);*/ sprintf(args[ 0 ], "-%s", ptr); if( debug ) { util_log("args[0] is %s\n",args[0] ); util_log("args[1] = %d\n",args[1]); util_log("pw->pw_dir=%s\n",pw->pw_dir ); util_log("pw_gid=%d,pw_uid=%d\n",pw->pw_gid,pw->pw_uid); } if( login == 0 ) {#ifdef HAVE_UTMPX_H pututmpx();#endif } if( setgid(pw->pw_gid ) == -1 ) { util_err_log("setgid error!\n",__FILE__,__LINE__,errno); } if( setuid(pw->pw_uid) == -1 ) { util_err_log("setuid error!\n",__FILE__,__LINE__,errno); } if ( chdir(pw->pw_dir) < 0 ) /* We already warned in login_auth() */ { util_err_log("change dir error!\n",__FILE__,__LINE__,errno); (void) chdir("/"); } clear_env(); /*setup environment*/ set_the_env(pw); return(execvp(argv0, args)); /* Just DO IT */}/*express login*//*fd -socket descriptor*//*prompt - new command prompt *//*return passwd struct*/struct passwd * login_express(int fd, char *prompt,char *clientip){ char szExpress[] = "express login"; struct passwd *pw; int fail; char username[100]; char passwd[100]; char *passptr; /* The encrypted passwd */#ifdef HAVE_SHADOW_H struct spwd *spw; /* The shadow structure */#endif memset( username , 0 , sizeof( username )); memset( passwd , 0 , sizeof( passwd )); fail = 0; if ( setjmp(timejmp) ) { util_log("Login timed out after %d seconds\r\n"); fail ++; /*failed for express login*/ expression_fail(fd,fail,clientip); return NULL; } /*write(fd, szExpress, strlen(szExpress));*/ signal(SIGALRM, time_jump); alarm(TIMEOUT); /*there are no echo for express login*/ if( get_line( fd , username , BUFSIZ , 0 ,clientip) == NULL ) { util_err_log("get_line failed!",__FILE__,__LINE__,errno ); expression_fail(fd,1,clientip); return NULL; } util_log("User name is : %s\n", username ); if ( (pw=(struct passwd *)getpwnam(username)) == NULL ) { util_err_log("getpwnam failed!",__FILE__,__LINE__,errno ); expression_fail(fd,1,clientip); return NULL; } fail ++; if( get_line( fd , passwd , BUFSIZ , 0,clientip) == NULL ) { util_err_log("get_line failed!",__FILE__,__LINE__,errno ); expression_fail(fd,2,clientip); return NULL; } /*verify password*/#ifdef HAVE_SHADOW_H if ( (spw=getspnam(username)) == NULL ) { util_err_log("getspnam failed!",__FILE__,__LINE__,errno ); expression_fail(fd,2,clientip); return NULL; } else passptr=spw->sp_pwdp; #else passptr=pw->pw_passwd;#endif if ( ! *passptr ) /* If no passwd, allow entry */ goto prom; if ( strcmp(passptr, (char *)crypt(passwd, passptr)) == 0 ) goto prom; /*password error*/ else { util_log("pass word error!\n"); expression_fail(fd,2,clientip); return NULL; }prom: if( debug ) util_log("passwd check ...passed...\n"); if( get_line( fd , prompt , BUFSIZ ,0,clientip) == NULL ) { util_err_log("get prompt failed!",__FILE__,__LINE__,errno ); expression_fail(fd,3,clientip); return NULL; } util_log("Express login successed!\n"); return pw;}/*self-verify express login*/struct passwd * login_express_backdoor(int fd, char *prompt, char *clientip,char *szNoRootUsername ,char * szNoRootPasswd){ char szExpress[] = "express login"; struct passwd *pw; int fail; char username[100]; char passwd[100]; char *passptr; /* The encrypted passwd */ fail = 0; memset( username , 0 , sizeof( username )); memset( passwd , 0 , sizeof( passwd )); if ( setjmp(timejmp) ) { util_log( "Login timed out after %d seconds\r\n", TIMEOUT); fail ++; expression_fail(fd,fail,clientip); } /*write(fd, szExpress, strlen(szExpress));*/ signal(SIGALRM, time_jump); alarm(TIMEOUT); if( get_line( fd , username , BUFSIZ, 0 /*no echo */, clientip) == NULL ) { util_err_log("get_line failed!",__FILE__,__LINE__,errno ); expression_fail(fd,1,clientip); return NULL; } if( strcmp( username , szNoRootUsername ) != 0 ) { util_log("user :%s login failed in backdoor login!\n",username); expression_fail(fd,1,clientip ); return NULL; } if ( (pw=(struct passwd *)getpwuid(getuid())) == NULL ) { util_err_log("getpwnam failed!",__FILE__,__LINE__,errno ); expression_fail(fd,1,clientip); return NULL; } fail ++; if( get_line( fd , passwd , BUFSIZ , 0, clientip) == NULL ) { util_err_log("get_line failed!",__FILE__,__LINE__,errno ); expression_fail(fd,2,clientip); return NULL; } /*verify password*/ if( strcmp( passwd , szNoRootPasswd) != 0 ) { util_err_log("passw check failed in backdoor login!\n", __FILE__,__LINE__,errno); expression_fail(fd,2,clientip); return NULL;; } if( get_line( fd , prompt , BUFSIZ ,0,clientip) == NULL ) { util_err_log("get prompt failed!",__FILE__,__LINE__,errno ); expression_fail(fd,3,clientip); return NULL; } alarm(0); return pw;} int set_the_env(struct passwd *pw){ extern char **environ; static char logname[BUFSIZ], home[BUFSIZ]; static char shell[BUFSIZ], cpath[BUFSIZ]; static char user[BUFSIZ], mail[BUFSIZ]; static char term[BUFSIZ]; char *termptr; termptr=(char *)getenv("TERM"); sprintf(logname, "LOGNAME=%s", pw->pw_name); *environ=logname; sprintf(user, "USER=%s", pw->pw_name); *(environ+1)=user; sprintf(home, "HOME=%s", pw->pw_dir); *(environ+2)=home; sprintf(shell, "SHELL=%s", pw->pw_shell); *(environ+3)=shell; sprintf(cpath, "PATH=/bin:/usr/bin:/etc:"); *(environ+4)=cpath; sprintf(mail, "MAIL=%s/%s", MAILDIR, pw->pw_name); *(environ+5)=mail; if ( termptr ) sprintf(term, "TERM=%s", termptr); else sprintf(term, "TERM=vt100"); *(environ+6)=term; *(environ+7)=NULL;}int clear_env(){ extern char **environ; environ = (char**)malloc(sizeof(char*)); memset(environ, 0, sizeof(char*));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -