/********************************************************************* mkpasswds.cc Haruhiko Okumura gcc mkpasswds.cc -lcrypt ./a.out some random passphrases < list_of_users *********************************************************************/ #include #include #include #include #include #include /* glibc ベースの Linux はこれが必要 */ using namespace std; typedef unsigned long uint32; // Mersenne Twister 乱数発生器 class MersenneTwister { static const int N = 624; static const int M = 397; static const uint32 MAT_A = 0x9908b0dfUL; static const uint32 UMASK = 0x80000000UL; static const uint32 LMASK = 0x7fffffffUL; int mti; uint32 mt[N]; // array for the state vector inline uint32 twist(uint32 u, uint32 v) { return (((u & UMASK) | (v & LMASK)) >> 1) ^ ((v & 1) * MAT_A); } public: void init(uint32 s) { mti = N; mt[0] = s & 0xffffffffUL; for (int i = 1; i < N; i++) { mt[i] = 1812433253UL * (mt[i-1] ^ (mt[i-1] >> 30)) + i; mt[i] &= 0xffffffffUL; } } void init(uint32 init_key[], int key_length) { init(19650218UL); int i = 1; int j = 0; for (int k = (N > key_length) ? N : key_length; k != 0; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1664525UL)) + init_key[j] + j; mt[i] &= 0xffffffffUL; if (++i >= N) { mt[0] = mt[N-1]; i = 1; } if (++j >= key_length) j = 0; } for (int k = N - 1; k != 0; k--) { mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL)) - i; mt[i] &= 0xffffffffUL; if (++i >= N) { mt[0] = mt[N-1]; i = 1; } } mt[0] = 0x80000000UL; } MersenneTwister(uint32 s = 5489) { init(s); } uint32 genrand_int32() { if (mti == N) { for (int k = 0; k < N - M; k++) mt[k] = mt[k+M] ^ twist(mt[k], mt[k+1]); for (int k = N - M; k < N - 1; k++) mt[k] = mt[k-(N-M)] ^ twist(mt[k], mt[k+1]); mt[N-1] = mt[M-1] ^ twist(mt[N-1], mt[0]); mti = 0; } uint32 y = mt[mti++]; y ^= (y >> 11); y ^= (y << 7) & 0x9d2c5680UL; y ^= (y << 15) & 0xefc60000UL; y ^= (y >> 18); return y; } }; MersenneTwister mt; // 0以上n未満の整数の乱数を生成 int irand(int n) { return int(mt.genrand_int32() % n); } void error(string s) { cerr << "mkpasswds: " << s << endl; exit(1); } string randompass() { string s; for (int i = 0; i < 3; i++) s += "abcdefghijkmnpqrstuvwxyz"[irand(24)]; for (int i = 3; i < 8; i++) s += "0123456789"[irand(10)]; return s; } char* salt() { static char s[3]; char a[65] = "abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789./"; s[0] = a[irand(64)]; s[1] = a[irand(64)]; s[2] = 0; return s; } int main(int argc, char* argv[]) { if (argc == 1) error("Usage: mkpasswds some random passphrases"); string passphrase = ""; for (int i = 1; i < argc; i++) passphrase += string(argv[i]); ofstream plain("plain"); if (!plain) error("Can't open"); ofstream passwd("passwd"); if (!passwd) error("Can't open"); ofstream shadow("shadow"); if (!shadow) error("Can't open"); ofstream doit("doit.sh"); if (!doit) error("Can't open"); doit << "#! /bin/sh\n\n"; int uid = 21160; // ユーザ番号の初期値 int gid = 600; // グループ番号 string shell = "/bin/passwd"; // ユーザシェル string dir = "/space/mieu/"; // 親ディレクトリ。最後は / string group = "student"; // グループ名 uint32* init_key = new uint32[passphrase.length() + 1]; init_key[0] = uint32(time(0)); for (int i = 0; i < passphrase.length(); i++) init_key[i+1] = int(passphrase[i]); mt.init(init_key, passphrase.length() + 1); int lastchg = int(time(0)) / (60 * 60 * 24); // 最終更新日(UNIX時間) string user; // ユーザ名 while (cin >> user) { string pass = randompass(); // パスワード char* cpass = crypt(pass.c_str(), salt()); // 暗号化パスワード plain << user << '\t' << pass << '\n'; passwd << user << ":x:" << uid << ':' << gid << ':' << user << ':' << dir << user << ':' << shell << '\n'; shadow << user << ':' << cpass << ':' << lastchg << "::::::\n"; doit << "mkdir -p " << dir << user << "/public_html\n"; doit << "chown -R " << user << '.' << group << ' ' << dir << user << '\n'; uid++; } }