Hello All,
Задача: чтобы у каждого юзера был 1 пароль на всё (ssh, samba, выход в
инет). И чтобы сам юзер мог этот пароль менять не дёргая меня. ssh,
samba настроены, на очереди squid. smb_auth требует контроллер домена,
в нашей одноранговой сети его нет (ну не нужен он). ncsa_auth -
неудобно и мне морока при смене паролей. Здесь пролетал исходник (с)
vasile <mail45***@p*****.ru>, который я и приспособил для работы в
связке со squid. Сам по себе он работает нормально: запускаю, набираю
логин пароль, получаю соответственно OK или ERR. А при запуске из-под
squid он тоже на первый взгляд работает. Но через некоторое время
сервер начинает страшно тормозить и обнаруживается, что в памяти висит
куча зациклившихся процессов shadow_auth.
Исходник shadow_auth.с
/*Данное решение проверенно на Linux и OpenBSD.
Если предполагается использование на системе с shadow password file то
нужно определить GNULINUX_TARGET (проще из Makefile передавать по
условию gcc -D GNULINUX_TARGET=1)*/
#ifdef GNULINUX_TARGET
#define _GNU_SOURCE
#define _XOPEN_SOURCE 4
#define _XOPEN_SOURCE_EXTENDED
#define _XOPEN_VERSION 4
#define _XPG4_2
#endif
#include <unistd.h>
#include <pwd.h>
#include <stdio.h>
#ifdef GNULINUX_TARGET
#include <shadow.h>
#endif
//0 - no such user
//1 - Auth ok
//-1 - no password, disabled, misc err
//-2 - Bad password
int sys_auth(const char *user, const char *pass, uid_t *uid)
{
struct passwd *pwe;
#ifdef GNULINUX_TARGET
struct spwd *spwe;
#endif
int result;
if ( (pwe = getpwnam(user)) )
{
if (uid)
*uid = pwe->pw_uid;
#ifdef GNULINUX_TARGET
memset(pwe->pw_passwd, 0, strlen(pwe->pw_passwd));
#endif
}
else
{
if (uid)
*uid = -1;
return 0;
}
result = 0;
#ifdef GNULINUX_TARGET
if ((spwe = getspnam(user)) && (pwe) && (spwe->sp_pwdp[0]) &&
(spwe->sp_pwdp[0] != '*') && (spwe->sp_pwdp[0] != '!'))
{
if (!strcmp(crypt(pass, spwe->sp_pwdp), spwe->sp_pwdp))
#else
if ((pwe) && (pwe->pw_passwd[0]) &&
(pwe->pw_passwd[0] != '*') && (pwe->pw_passwd[0] != '!'))
{
if (!strcmp(crypt(pass, pwe->pw_passwd), pwe->pw_passwd))
#endif
result = 1;
else
result = -2;
}
else
result = -1;
#ifdef GNULINUX_TARGET
if (spwe) memset(spwe, 0, sizeof(struct spwd));
#endif
if (pwe) memset(pwe, 0, sizeof(struct passwd));
return result;
}
int main(int argc, char *argv[])
{
char user[101], password[101];
uid_t uid;
while (1)
{
scanf("%100s %100s", user, password);
if (sys_auth(user, password, &uid) == 1)
printf("OK\n");
else printf("ERR\n");
fflush(stdout);
}
}