Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
LSH
lsh
Commits
853c8bef
Commit
853c8bef
authored
Oct 24, 1998
by
Niels Möller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use the login_method abstraction. Use setuid and related functions.
Rev: src/server_password.c:1.3
parent
26227133
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
111 additions
and
83 deletions
+111
-83
src/server_password.c
src/server_password.c
+111
-83
No files found.
src/server_password.c
View file @
853c8bef
...
...
@@ -25,43 +25,59 @@
#include "password.h"
#include "charset.h"
#include "format.h"
#include "parse.h"
#include "userauth.h"
#include "werror.h"
#include "xalloc.h"
#include <string.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
static
struct
lsh_string
*
format_cstring
(
char
*
s
)
{
return
s
?
ssh_format
(
"%lz"
,
s
)
:
NULL
;
}
static
struct
lsh_string
*
make_cstring
(
struct
lsh_string
*
s
,
int
free
)
{
struct
lsh_string
*
res
;
if
(
memchr
(
s
->
data
,
'\0'
,
s
->
length
))
{
if
(
free
)
lsh_string_free
(
s
);
return
0
;
}
res
=
ssh_format
(
"%lS"
,
s
);
if
(
free
)
lsh_string_free
(
s
);
return
res
;
}
/* NOTE: Calls function using the *disgusting* convention of returning
* pointers to static buffers. */
struct
unix_user
*
lookup_user
(
lsh_string
*
name
)
struct
unix_user
*
lookup_user
(
struct
lsh_string
*
name
,
int
free
)
{
struct
passwd
*
passwd
;
char
*
u
;
struct
unix_user
*
res
;
/* Convert name to a NULL-terminated string */
u
=
alloca
(
name
->
length
+
1
);
memcpy
(
u
,
name
->
data
,
name
->
length
);
u
[
name
->
length
]
=
0
;
name
=
make_cstring
(
name
,
free
);
if
(
strlen
(
u
)
<
user
->
length
)
{
/* User name includes NULL-characters. */
return
0
;
}
if
(
!
(
passwd
=
getpwnam
(
u
);))
if
(
!
name
)
return
0
;
if
(
!
(
passwd
=
getpwnam
(
name
->
data
)))
return
0
;
NEW
(
res
);
res
->
uid
=
passwd
->
pw_uid
;
#if 0
res->username = ssh_format("%lz", passwd->name);
#endif
res
->
gid
=
passwd
->
pw_gid
;
res
->
username
=
name
;
res
->
passwd
=
format_cstring
(
passwd
->
pw_passwd
);
res
->
home
=
format_cstring
(
passwd
->
pw_dir
);
...
...
@@ -71,38 +87,30 @@ struct unix_user *lookup_user(lsh_string *name)
/* NOTE: Calls function using the *disgusting* convention of returning
* pointers to static buffers. */
int
verify_password
(
struct
unix_user
*
user
,
struct
lsh_string
*
password
)
struct
lsh_string
*
password
,
int
free
)
{
char
*
p
;
char
*
salt
;
char
*
crypted_passwd
;
/* Convert password to a NULL-terminated string */
p
=
alloca
(
password
->
length
+
1
);
p
assword
=
make_cstring
(
password
,
free
);
memcpy
(
p
,
password
->
data
,
password
->
length
);
p
[
password
->
length
]
=
0
;
if
(
strlen
(
p
)
<
passwd
->
length
)
if
(
!
user
->
passwd
||
(
user
->
passwd
->
length
<
2
)
)
{
/* Password includes NULL-characters. */
/* FIXME: How are accounts without passwords handled? */
lsh_string_free
(
password
);
return
0
;
}
if
(
!
user
->
passwd
)
salt
=
user
->
passwd
->
data
;
if
(
strcmp
(
crypt
(
password
->
data
,
salt
),
user
->
passwd
->
data
))
{
/* How are accounts without passwords handled? */
/* Passwd doesn't match */
lsh_string_free
(
password
);
return
0
;
}
if
(
user
->
passwd
->
length
<
2
)
return
0
;
salt
=
user
->
passwd
->
data
;
if
(
strcmp
(
crypt
(
p
,
salt
),
user
->
passwd
))
/* Passwd doesn't match */
return
0
;
lsh_string_free
(
password
);
return
1
;
}
...
...
@@ -110,6 +118,7 @@ struct unix_authentication
{
struct
userauth
super
;
struct
login_method
*
login
;
struct
alist
*
services
;
/* Services allowed */
};
...
...
@@ -117,18 +126,17 @@ static int do_authenticate(struct userauth *c,
struct
lsh_string
*
username
,
int
requested_service
,
struct
simple_buffer
*
args
,
struct
ssh_service
**
service
)
struct
ssh_service
**
result
)
{
struct
unix_authentication
*
closure
=
(
struct
unix_authentication
*
)
c
;
struct
lsh_string
*
password
=
NULL
;
struct
unix_service
*
login
;
struct
ssh_service
*
service
;
MDEBUG
(
closure
);
if
(
!
(
(
login
=
ALIST_GET
(
closure
->
services
,
requested_service
))))
if
(
!
(
(
service
=
ALIST_GET
(
closure
->
services
,
requested_service
))))
{
lsh_string_free
(
user
);
lsh_string_free
(
user
name
);
return
LSH_AUTH_FAILED
;
}
...
...
@@ -136,8 +144,8 @@ static int do_authenticate(struct userauth *c,
if
(
!
username
)
return
0
;
if
(
parse_string_copy
(
&
buffer
,
&
password
)
&&
parse_eod
(
&
buffer
))
if
(
(
password
=
parse_string_copy
(
args
)
)
&&
parse_eod
(
args
))
{
struct
unix_user
*
user
;
int
access
;
...
...
@@ -150,8 +158,7 @@ static int do_authenticate(struct userauth *c,
return
LSH_AUTH_FAILED
;
}
user
=
lookup_user
(
user_length
,
username
);
lsh_string_free
(
user
);
user
=
lookup_user
(
username
,
1
);
if
(
!
user
)
{
...
...
@@ -159,60 +166,60 @@ static int do_authenticate(struct userauth *c,
return
LSH_AUTH_FAILED
;
}
access
=
verify_password
(
user
,
password
);
lsh_string_free
(
password
);
access
=
verify_password
(
user
,
password
,
1
);
if
(
access
)
return
LOGIN
(
login
,
user
);
{
*
result
=
LOGIN
(
closure
->
login
,
user
,
service
);
return
LSH_OK
|
LSH_GOON
;
}
else
{
lsh_f
ree
(
user
);
/* FIXME: F
ree
user
struct */
return
LSH_AUTH_FAILED
;
}
}
lsh_string_free
(
user
);
lsh_string_free
(
user
name
);
if
(
password
)
lsh_string_free
(
password
);
return
0
;
}
struct
userauth
*
make_unix_userauth
(
struct
alist
*
services
)
struct
userauth
*
make_unix_userauth
(
struct
login_method
*
login
,
struct
alist
*
services
)
{
struct
unix_authentication
*
closure
;
NEW
(
closure
);
closure
->
super
.
authenticate
=
do_authenticate
;
closure
->
login
=
login
;
closure
->
services
=
services
;
return
&
closure
->
super
;
}
struct
setuid_
handler
struct
setuid_
service
{
struct
unix
_service
super
;
struct
ssh
_service
super
;
struct
unix_user
*
user
;
/* Service to start once we have changed to the correct uid. */
struct
ssh_service
*
service
;
};
static
int
do_setuid
(
struct
unix_service
*
closure
,
struct
user
)
static
int
do_setuid
(
struct
ssh_service
*
c
,
struct
ssh_connection
*
connection
)
{
uid_t
servers_uid
=
get_uid
();
struct
setuid_service
*
closure
=
(
struct
setuid_service
*
)
c
;
uid_t
server_uid
=
getuid
();
int
res
=
0
;
struct
*
pw
;
pw
=
getpwuid
(
user
->
uid
);
if
(
!
pw
)
{
werror
(
"do_fork: User disappeared!
\n
"
);
return
LSH_AUTH_FAILED
;
}
if
(
servers_uid
!=
user
->
uid
)
MDEBUG
(
closure
);
if
(
server_uid
!=
closure
->
user
->
uid
)
{
if
(
server
s
_uid
)
if
(
server_uid
)
/* Not root */
return
LSH_AUTH_FAILED
;
...
...
@@ -229,17 +236,17 @@ static int do_setuid(struct unix_service *closure, struct user)
* wrong, the server will think that the user is logged in
* under his or her user id, while in fact the process is
* still running as root. */
if
(
initgroups
(
pw
->
pw_name
,
pw
->
pw_
gid
)
<
0
)
if
(
initgroups
(
closure
->
user
->
username
->
data
,
closure
->
user
->
gid
)
<
0
)
{
werror
(
"initgroups failed: %s
\n
"
,
strerror
(
errno
));
return
LSH_FAIL
|
LSH_DIE
|
LSH_KILL_OTHERS
;
}
if
(
setgid
(
pw
->
pw_
gid
)
<
0
)
if
(
setgid
(
closure
->
user
->
gid
)
<
0
)
{
werror
(
"setgid failed: %s
\n
"
,
strerror
(
errno
));
return
LSH_FAIL
|
LSH_DIE
|
LSH_KILL_OTHERS
;
}
if
(
setuid
(
pw
->
pw_
uid
)
<
0
)
if
(
setuid
(
closure
->
user
->
uid
)
<
0
)
{
werror
(
"setuid failed: %s
\n
"
,
strerror
(
errno
));
return
LSH_FAIL
|
LSH_DIE
|
LSH_KILL_OTHERS
;
...
...
@@ -255,32 +262,53 @@ static int do_setuid(struct unix_service *closure, struct user)
/* Change to user's home directory. FIXME: If the server is running
* as the same user, perhaps it's better to use $HOME? */
if
(
!
pw
->
pw_dir
)
if
(
!
closure
->
user
->
home
)
{
if
(
chdir
(
"/"
)
<
0
)
fatal
(
"Strange:
pw->pw_dir i
s NULL, and chdir(
\"
/
\"
) failed: %s
\n
"
,
fatal
(
"Strange:
home directory wa
s NULL, and chdir(
\"
/
\"
) failed: %s
\n
"
,
strerror
(
errno
));
}
else
if
(
chdir
(
pw
->
pw_dir
)
<
0
)
if
(
chdir
(
closure
->
user
->
home
->
data
)
<
0
)
{
werror
(
"chdir to %s failed (using / instead): %s
\n
"
,
pw
->
pw_dir
?
pw
->
pw_dir
:
"none"
,
strerror
(
errno
));
closure
->
user
->
home
?
(
char
*
)
closure
->
user
->
home
->
data
:
"none"
,
strerror
(
errno
));
if
(
chdir
(
"/"
)
<
0
)
fatal
(
"chdir(
\"
/
\"
) failed: %s
\n
"
,
strerror
(
errno
));
}
/* Initialize the service, somehow */
/* Initialize environment, somehow. In particular, the HOME and
* LOGNAME variables */
/* If closure->user is not needed anymore, deallocate it (and set
* the pointer to NULL, to tell gc about that). */
return
res
|
SERVICE_INIT
(
closure
->
service
,
connection
);
}
struct
unix_service
*
make_setuid_handler
(
struct
ssh_service
*
service
)
static
struct
ssh_service
*
do_login
(
struct
login_method
*
closure
,
struct
unix_user
*
user
,
struct
ssh_service
*
service
)
{
struct
setuid_
handler
*
closu
re
;
struct
setuid_
service
*
re
s
;
NEW
(
closure
);
MDEBUG
(
closure
);
NEW
(
res
);
res
->
super
.
init
=
do_setuid
;
res
->
user
=
user
;
res
->
service
=
service
;
closure
->
super
.
login
=
do_setuid
;
closure
->
service
=
service
;
return
&
res
->
super
;
}
return
&
closure
->
super
;
struct
login_method
*
make_unix_login
(
void
)
{
struct
login_method
*
self
;
NEW
(
self
);
self
->
login
=
do_login
;
return
self
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment