Article View: es.comp.os.linux.programacion
Article #8150Re: Comprobar comtraseña
From: J.A. Gutierrez
Date: Tue, 17 Dec 2002 18:37
Date: Tue, 17 Dec 2002 18:37
185 lines
6309 bytes
6309 bytes
Jose A <MAQUI000@.nospan.mundo-r.com> wrote:
: quantium escribi�:
:> Hola a todos.
: Hola.
:
:> �Sabeis como puedo comprobar si una contrase�a insertada es la del
:> usuario que la ha insertado?
:>
:> He estado mirando en google y en la faq de unix, se que lo tiros van por
:> strcmp y crypt, pero no me queda nada clar, �me podriais poner un
:> ejemplo sobre su uso?
: Puedes usar algo asi:
: #include <shadow.h>
esto depende de la variante de unix utilizada.
(ver mas abajo)
: int main (int argc, char *argv[0]) {
: char *pwd, salt[11], *passwd, *tpwd;
: struct spwd *p;
: if (argc < 3) {
: printf ("Usar %s nombre password\n", argv[0]);
: exit (1);
: }
:
: // Limpiamos la variable salt para evitar problemas.
no es bueno usar comentarios de C++ en programas de C
: bzero (salt, sizeof (salt));
no es bueno usar funciones poco portables (BSD)
Ademas, en realidad, no es necesario ni copiar la sal ni
poner el buffer a cero.
> CONFORMING TO
> 4.3BSD. This function is deprecated -- use memset in new
> programs.
: // Bloqueamos el fichero "/etc/shadow" para que no se
: // modifique mientras accedemos a sus datos.
: lckpwdf ();
: p = getspnam (argv[1]);
: // Y aqu� lo desbloqueamos.
: ulckpwdf ();
:
creo que por lo general no se considera necesario bloquear el
shadow antes de leerlo, solamente antes de modificarlo.
: pwd = argv[2];
: passwd = p->sp_pwdp;
: // Dentro de este bloque if comprobamos el tipo de
: // password que se usa, si empieza por "$1$", es
: // del tipo md5, y copiamos los 11 primeros caracteres
: // del password que est�n formados por la identificaci�n
: // (3 caracteres) y la salt (8 caracteres), por ejemplo:
: // $1$aT���TjK
: // Estos 11 caracteres son usados para que la funci�n crypt
: // identifique la password como del tipo md5.
: if (memcmp (passwd, "$1$", 3) == 0) {
: strncpy (salt, passwd, 11);
: // Si no es del tipo des y se cogen solo los 2 primeros
: // caracteres.
: } else {
: strncpy (salt, passwd, 2);
: }
mas facil, le pasas a crypt() directemente el password encriptado
en el campo salt y el solo se las apa~na.
Ademas, es mas portable.
tpwd = crypt (pwd, p->sp_pwdp);
: // Aqu� se encripta la password pasada al programa y
: // a continuaci�n se compara con la almacenada en el
: // fichero "/etc/shadow".
: tpwd = (char *) crypt (pwd, salt);
notese que el cast es innecesario.
: if (strcmp (tpwd, passwd) == 0) {
: printf ("Las password son iguales\n");
: } else {
: printf ("Las password son distintas\n");
: }
: return 0;
: }
: y el uso es as�:
: ./nombre_fichero usuario password
notese que requiere privilegios de root.
Alternativa:
---------------------------------------------------------------------------
[...]
#include <pwd.h>
#include <sys/param.h>
#ifdef _USE_SHADOW_
# include <shadow.h>
struct spwd *spasswd;
#endif
#ifdef _BSD_
extern char *sys_errlist[];
# define raise(s) kill(getpid(),(s))
# define strerror(e) sys_errlist[(e)]
extern char *crypt( char *key, char *salt);
extern char *getpass( char *prompt);
#else
#include <crypt.h>
#endif
[...]
if ( NULL == ( pwd = getpwuid ( getuid () )))
{
output("getpwuid failed for %s (%s)",
getuid(), strerror(errno) );
error = errno;
}
else
{
sprintf(s, "%s's password? ", pwd->pw_name);
if ( NULL == (pass = getpass(s)))
{
output( "getpass failed for %s (%s)",
pwd->pw_name, strerror(errno));
error = errno;
}
else
{
#ifdef _USE_SHADOW_
if ( NULL == ( spasswd = getspnam(pwd->pw_name) ))
{
output( "getspnam failed for %s (%s)\n",
pwd->pw_name, strerror(errno));
exit(errno);
}
if (strcmp(spasswd->sp_pwdp, crypt(pass, spasswd->sp_pwdp)))
#else
if (strcmp(pwd->pw_passwd, crypt(pass, pwd->pw_passwd)))
#endif
{
output( "incorrect password for %s\n",
pwd->pw_name);
}
else
{
[...]
}
}
}
---------------------------------------------------------------------------
La cosa se puede complicar aun mas con cosas como crypt16, bigcrypt
y demas, pero en fin, con lo de arriba ya vale para bastantes casos...
PS: Notese en se utilza getpass, que segun linux, tampoco deberia
utilizarse:
DESCRIPTION
This function is obsolete. Do not use it.
En solaris existe getpassphrase()...
--
PGP and other useless info at \
http://www.cps.unizar.es/~spd/ \
finger://daphne.cps.unizar.es/spd \ Timeo Danaos et dona ferentes
ftp://ivo.cps.unizar.es/pub/ \ (Virgilio)
Technical Details
Message-ID:
<atnqsp$pkd$1@news.unizar.es>Path:
arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!news1.google.com!newsfeed.stanford.edu!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!newsfeed.icl.net!newsfeed.fjserv.net!newsfeed.icl.net!newsfeed.fjserv.net!isdnet!news.rediris.es!news.unizar.es!not-for-mailReferences:
<atgjct$13knnp$1@ID-129971.news.dfncis.de> <atncbv$k5m81@cesio.mundo-r.com>Show Full Headers
Complete Article Headers
X-Google-Language: SPANISH,ASCII
X-Google-Thread: f86c8,249be857bbf5a850
X-Google-Attributes: gidf86c8,public
X-Google-ArrivalTime: 2002-12-17 09:57:09 PST
Path: arc1-ca.pugleaf.net!archiver1.google.com!news2.google.com!news1.google.com!newsfeed.stanford.edu!news-spur1.maxwell.syr.edu!news.maxwell.syr.edu!newsfeed.icl.net!newsfeed.fjserv.net!newsfeed.icl.net!newsfeed.fjserv.net!isdnet!news.rediris.es!news.unizar.es!not-for-mail
From: "J.A. Gutierrez" <spd@daphne.cps.unizar.es>
Newsgroups: es.comp.os.linux.programacion
Subject: Re: Comprobar comtraseña
Date: 17 Dec 2002 18:37:13 GMT
Organization: Rank
Lines: 185
Message-ID: <atnqsp$pkd$1@news.unizar.es>
References: <atgjct$13knnp$1@ID-129971.news.dfncis.de> <atncbv$k5m81@cesio.mundo-r.com>
NNTP-Posting-Host: daphne.cps.unizar.es
Mime-Version: 1.0
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 8bit
X-Trace: news.unizar.es 1040150233 26253 155.210.152.20 (17 Dec 2002 18:37:13 GMT)
X-Complaints-To: usenet@news.unizar.es
NNTP-Posting-Date: 17 Dec 2002 18:37:13 GMT
User-Agent: tin/1.4.5-20010409 ("One More Nightmare") (UNIX) (IRIX/6.2 (IP22))