1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
|
#include <unistd.h> #include <pwd.h> #include <crypt.h> #include <shadow.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h>
#define COND_RET(x, ret, msg...) \ do { \ errno = 0;\ if(!(x)) { \ if(errno == 0)fprintf(stderr, "%s:%d\nunmet condition:\"%s\"\n", __FILE__, __LINE__, #x); \ else fprintf(stderr, "%s:%d\nerror: %s\nunmet condition:\"%s\"\n", __FILE__, __LINE__,strerror(errno), #x); \ fprintf(stderr, msg); \ fprintf(stderr, "\n");\ ret \ } \ } while(0)
#define CHECK(x, msg...) COND_RET(x, return -1;, msg) #define CHECK_EXIT(x, msg...) COND_RET(x, exit(1);, msg)
int main(int argc, char *argv[]) { char *filename = strrchr(argv[0], '/'); if(filename == NULL) { filename = argv[0]; } else { filename++; } if(!strcmp(filename, "sudo")) { CHECK_EXIT(argc >= 2, "Usage: %s [-u user] exec [args...]", argv[0]); uid_t user = 0; char *username = "root"; char **exec = &argv[1]; char *shadow = NULL; if (argv[1][0] == '-') { username = argv[2]; exec = &argv[3]; } struct passwd *usrpwd; CHECK_EXIT((usrpwd = getpwnam(username)) != NULL, "username:%s not found", username); user = usrpwd->pw_uid; shadow = usrpwd->pw_passwd; printf("shaowd=%s\n", shadow); char *pass = getpass("password:"); CHECK_EXIT(setuid(0) != -1, "execute 'su; sudo chmod u+s %s' may fix this problem", argv[0]); if(!strcmp(shadow, "x")) { struct spwd *shadowpwd; CHECK_EXIT((shadowpwd = getspnam(username)) != NULL, "shadowpwd not found"); shadow = shadowpwd->sp_pwdp; pass = crypt(pass, shadow); } printf("shaowd=%s, pass=%s\n", shadow, pass); CHECK_EXIT(!strcmp(shadow, pass), "password not match!"); CHECK_EXIT(setuid(user) != -1, ""); CHECK_EXIT(execvp(exec[0], exec) != -1, ""); } else { struct passwd *pwd = NULL; uid_t uid = 0; if(argc > 1) { char *end = NULL; uid = strtoul(argv[1], &end, 10); CHECK_EXIT((end != NULL && end != argv[1]), "%s is not a number\n", argv[1]); } else { uid = getuid(); } CHECK_EXIT((pwd = getpwuid(uid)) != NULL, "uid:%u not found", uid); printf("uid:%u, user:%s\n", pwd->pw_uid, pwd->pw_name); } return 0; }
|