Created
June 3, 2010 10:37
-
-
Save shimarin/423724 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// smbauth.cpp | |
// g++ smbauth.cpp -DPRIVATE_DIR=\"`testparm -s --parameter-name="private dir"`\" -lssl -lext2fs -o smbauth | |
// chmod 711 smbauth | |
// chmod u+s smbauth | |
// mv smbauth /usr/sbin/ | |
#include <stdio.h> | |
#include <ctype.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
#include <fcntl.h> | |
#include <stdint.h> | |
#include <openssl/md4.h> | |
#include <iconv.h> | |
#include <ext2fs/tdb.h> | |
#define STATUS_OK 0 /* Valid Login */ | |
#define STATUS_UNKNOWN 1 /* Login doesn't exist or password incorrect */ | |
#define STATUS_INVALID 2 /* Password was incorrect */ | |
#define STATUS_BLOCKED 3 /* UID is below minimum allowed to use this */ | |
#define STATUS_EXPIRED 4 /* Login ID has passed it's expiration date */ | |
#define STATUS_PW_EXPIRED 5 /* Password has expired and must be changed */ | |
#define STATUS_NOLOGIN 6 /* Logins have been turned off */ | |
#define STATUS_MANYFAILS 7 /* Bad login limit exceeded */ | |
#define STATUS_INT_USER 50 /* pwauth was run by wrong uid */ | |
#define STATUS_INT_ARGS 51 /* login/password not passed in correctly */ | |
#define STATUS_INT_ERR 52 /* Miscellaneous internal errors */ | |
#define STATUS_INT_NOROOT 53 /* pwauth cannot read password database */ | |
#define IVAL(buf,pos) (*(const uint32_t *)((const char *)(buf) + (pos))) | |
#ifndef PRIVATE_DIR | |
#define PRIVATE_DIR "/var/lib/samba/private" | |
#endif | |
#ifndef BFSZ | |
# define BFSZ 1024 | |
#endif | |
uint32_t get_dword(unsigned char*& buf, size_t &len_left) | |
{ | |
if (len_left < 4) { | |
throw len_left; | |
} | |
uint32_t ret = IVAL(buf, 0); | |
buf += 4; | |
len_left -= 4; | |
return ret; | |
} | |
void skip_string(unsigned char*& buf, size_t &len_left) | |
{ | |
uint32_t len = get_dword(buf, len_left); | |
if (len_left < len) { | |
throw len; | |
} | |
buf += len; | |
len_left -= len; | |
} | |
int main() | |
{ | |
// stdinからユーザー名とパスワードを1行ずつでもらう | |
char login[BFSZ+1], passwd[BFSZ+1]; | |
if (fgets(login, BFSZ, stdin) == NULL || | |
fgets(passwd, BFSZ, stdin) == NULL) | |
return STATUS_INT_ARGS; | |
char *c; | |
if ((c= strchr(login,'\n')) != NULL) *c= '\0'; | |
if ((c= strchr(passwd,'\n')) != NULL) *c= '\0'; | |
// パスワードをまずはUCS-2LEに変換する | |
char* utf8_text = new char[strlen(passwd) + 1]; | |
strcpy(utf8_text, passwd); | |
size_t utf8_len = strlen(utf8_text); | |
size_t ucs2buf_len = utf8_len * 2; | |
char* ucs2_text = new char[ucs2buf_len]; | |
char* inbuf = utf8_text; | |
char* outbuf = ucs2_text; | |
size_t inbytesleft = strlen(utf8_text); | |
size_t outbytesleft = ucs2buf_len; | |
iconv_t ic = iconv_open("UCS-2LE", "UTF-8"); | |
size_t result = iconv(ic, &inbuf, &inbytesleft, &outbuf, &outbytesleft); | |
iconv_close(ic); | |
delete [] utf8_text; | |
if (result < 0) { | |
delete [] ucs2_text; | |
return STATUS_INT_ERR; | |
} | |
// UCS-2LEに変換されたパスワードのMD4ハッシュを取る | |
unsigned char md4[MD4_DIGEST_LENGTH]; | |
MD4((unsigned char*)ucs2_text, ucs2buf_len - outbytesleft, md4); | |
delete [] ucs2_text; // UCS-2LEのパスワードはもういらないので削除 | |
TDB_CONTEXT * tdb = tdb_open(PRIVATE_DIR"/passdb.tdb", 0, 0, O_RDONLY, 0666); | |
if (tdb == NULL) { | |
return STATUS_INT_NOROOT; | |
} | |
// sambaのパスワードデータベースからパスワードを読み込む | |
// データベースではユーザー名は常に小文字で扱う | |
for (char* pt = login; *pt; pt++) { *pt = tolower(*pt); } | |
char* key_string = new char[strlen(login) + 6]; | |
sprintf(key_string, "USER_%s", login); | |
TDB_DATA key; | |
key.dptr = (unsigned char*)key_string; | |
key.dsize = strlen(login) + 6; | |
TDB_DATA data = tdb_fetch(tdb, key); | |
delete [] key_string; | |
if (data.dptr == NULL) { | |
return STATUS_UNKNOWN; | |
} | |
size_t left_len = data.dsize; | |
// dddddddBBBBBBBBBBBBddBB←これ | |
unsigned char* buf = data.dptr; | |
try { | |
for (int i = 0; i < 7; i++) { get_dword(buf, left_len); } // ddddddd | |
for (int i = 0; i < 12; i++) { skip_string(buf, left_len); } | |
get_dword(buf, left_len); //d | |
get_dword(buf, left_len); //d | |
skip_string(buf, left_len); // B | |
if (left_len < 4) throw (size_t)4; | |
uint32_t len = IVAL(buf, 0); | |
if (left_len < len) throw (size_t)len; | |
unsigned char* password = new unsigned char[len]; | |
memcpy(password, buf + 4, len); | |
int result = memcmp(md4, password, MD4_DIGEST_LENGTH); | |
delete [] password; | |
if (result != 0) return STATUS_INVALID; | |
} | |
catch (size_t len_needed) { | |
fprintf(stderr, "Buffer length is shorter than needed\n"); | |
tdb_close(tdb); | |
return -1; | |
} | |
tdb_close(tdb); | |
return STATUS_OK; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// unixgroup.cpp | |
// g++ unixgroup.cpp -o unixgroup | |
// mv unixgroup /usr/sbin/ | |
#include <stdio.h> | |
#include <string.h> | |
#include <sys/types.h> | |
#include <grp.h> | |
#include <pwd.h> | |
bool check_group(const char* user, const char* group) | |
{ | |
struct passwd* p = getpwnam(user); | |
struct group* g = getgrnam(group); | |
if (g->gr_gid == p->pw_gid) return true; | |
for (int i = 0; g->gr_mem[i] != NULL; i++) { | |
if (strcmp(g->gr_mem[i], user) == 0) return true; | |
} | |
return false; | |
} | |
int main() | |
{ | |
char user[100], groups[100], *group, *p; | |
if (fgets(user, sizeof(user), stdin) == NULL) return 2; | |
if ((p= strchr(user, '\n')) == NULL) return 4; | |
*p= '\0'; | |
if (fgets(groups, sizeof(groups), stdin) == NULL) return 3; | |
if ((p= strchr(groups, '\n')) == NULL) return 5; | |
*p= '\0'; | |
group= strtok(groups, " "); | |
while (group != NULL) { | |
if (check_group(user, group)) | |
return 0; /* User is in group */ | |
group= strtok(NULL, " "); | |
} | |
return 1; /* User is not in any group */ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment