222 lines
7.3 KiB
C
222 lines
7.3 KiB
C
/*
|
|
* Copyright (c) 2008, Jamie Beverly.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification, are
|
|
* permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
* conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
|
* provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY Jamie Beverly ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Jamie Beverly OR
|
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* The views and conclusions contained in the software and documentation are those of the
|
|
* authors and should not be interpreted as representing official policies, either expressed
|
|
* or implied, of Jamie Beverly.
|
|
*/
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include "includes.h"
|
|
#include "config.h"
|
|
|
|
#include "openbsd-compat/sys-queue.h"
|
|
#include "xmalloc.h"
|
|
#include "log.h"
|
|
#include "buffer.h"
|
|
#include "key.h"
|
|
#include "authfd.h"
|
|
#include <stdio.h>
|
|
#include <openssl/evp.h>
|
|
#include "ssh2.h"
|
|
#include "misc.h"
|
|
|
|
#include "userauth_pubkey_from_id.h"
|
|
#include "identity.h"
|
|
#include "get_command_line.h"
|
|
extern char **environ;
|
|
|
|
static char *
|
|
log_action(char ** action, size_t count)
|
|
{
|
|
size_t i;
|
|
char *buf = NULL;
|
|
|
|
if (count == 0)
|
|
return NULL;
|
|
|
|
buf = pamsshagentauth_xcalloc((count * MAX_LEN_PER_CMDLINE_ARG) + (count * 3), sizeof(*buf));
|
|
for (i = 0; i < count; i++) {
|
|
strcat(buf, (i > 0) ? " '" : "'");
|
|
strncat(buf, action[i], MAX_LEN_PER_CMDLINE_ARG);
|
|
strcat(buf, "'");
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
void
|
|
agent_action(Buffer *buf, char ** action, size_t count)
|
|
{
|
|
size_t i;
|
|
pamsshagentauth_buffer_init(buf);
|
|
|
|
pamsshagentauth_buffer_put_int(buf, count);
|
|
|
|
for (i = 0; i < count; i++) {
|
|
pamsshagentauth_buffer_put_cstring(buf, action[i]);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
pamsshagentauth_session_id2_gen(Buffer * session_id2, const char * user,
|
|
const char * ruser, const char * servicename)
|
|
{
|
|
char *cookie = NULL;
|
|
uint8_t i = 0;
|
|
uint32_t rnd = 0;
|
|
uint8_t cookie_len;
|
|
char hostname[256] = { 0 };
|
|
char pwd[1024] = { 0 };
|
|
time_t ts;
|
|
char ** reported_argv = NULL;
|
|
size_t count = 0;
|
|
char * action_logbuf = NULL;
|
|
Buffer action_agentbuf;
|
|
uint8_t free_logbuf = 0;
|
|
char * retc;
|
|
int32_t reti;
|
|
|
|
rnd = pamsshagentauth_arc4random();
|
|
cookie_len = ((uint8_t) rnd);
|
|
while (cookie_len < 16) {
|
|
cookie_len += 16; /* Add 16 bytes to the size to ensure that while the length is random, the length is always reasonable; ticket #18 */
|
|
}
|
|
|
|
cookie = pamsshagentauth_xcalloc(1,cookie_len);
|
|
|
|
for (i = 0; i < cookie_len; i++) {
|
|
if (i % 4 == 0) {
|
|
rnd = pamsshagentauth_arc4random();
|
|
}
|
|
cookie[i] = (char) rnd;
|
|
rnd >>= 8;
|
|
}
|
|
|
|
count = pamsshagentauth_get_command_line(&reported_argv);
|
|
if (count > 0) {
|
|
free_logbuf = 1;
|
|
action_logbuf = log_action(reported_argv, count);
|
|
agent_action(&action_agentbuf, reported_argv, count);
|
|
pamsshagentauth_free_command_line(reported_argv, count);
|
|
}
|
|
else {
|
|
action_logbuf = "unknown on this platform";
|
|
pamsshagentauth_buffer_init(&action_agentbuf); /* stays empty, means unavailable */
|
|
}
|
|
|
|
/*
|
|
action = getenv("SUDO_COMMAND");
|
|
if(!action) {
|
|
action = getenv("PAM_AUTHORIZED_ACTION");
|
|
if(!action) {
|
|
action = empty;
|
|
}
|
|
}
|
|
*/
|
|
|
|
reti = gethostname(hostname, sizeof(hostname) - 1);
|
|
retc = getcwd(pwd, sizeof(pwd) - 1);
|
|
time(&ts);
|
|
|
|
pamsshagentauth_buffer_init(session_id2);
|
|
|
|
pamsshagentauth_buffer_put_int(session_id2, PAM_SSH_AGENT_AUTH_REQUESTv1);
|
|
/* pamsshagentauth_debug3("cookie: %s", pamsshagentauth_tohex(cookie, cookie_len)); */
|
|
pamsshagentauth_buffer_put_string(session_id2, cookie, cookie_len);
|
|
/* pamsshagentauth_debug3("user: %s", user); */
|
|
pamsshagentauth_buffer_put_cstring(session_id2, user);
|
|
/* pamsshagentauth_debug3("ruser: %s", ruser); */
|
|
pamsshagentauth_buffer_put_cstring(session_id2, ruser);
|
|
/* pamsshagentauth_debug3("servicename: %s", servicename); */
|
|
pamsshagentauth_buffer_put_cstring(session_id2, servicename);
|
|
/* pamsshagentauth_debug3("pwd: %s", pwd); */
|
|
if(retc)
|
|
pamsshagentauth_buffer_put_cstring(session_id2, pwd);
|
|
else
|
|
pamsshagentauth_buffer_put_cstring(session_id2, "");
|
|
/* pamsshagentauth_debug3("action: %s", action_logbuf); */
|
|
pamsshagentauth_buffer_put_string(session_id2, action_agentbuf.buf + action_agentbuf.offset, action_agentbuf.end - action_agentbuf.offset);
|
|
if (free_logbuf) {
|
|
pamsshagentauth_xfree(action_logbuf);
|
|
pamsshagentauth_buffer_free(&action_agentbuf);
|
|
}
|
|
/* pamsshagentauth_debug3("hostname: %s", hostname); */
|
|
if(reti >= 0)
|
|
pamsshagentauth_buffer_put_cstring(session_id2, hostname);
|
|
else
|
|
pamsshagentauth_buffer_put_cstring(session_id2, "");
|
|
/* pamsshagentauth_debug3("ts: %ld", ts); */
|
|
pamsshagentauth_buffer_put_int64(session_id2, (uint64_t) ts);
|
|
|
|
free(cookie);
|
|
return;
|
|
}
|
|
|
|
int
|
|
pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename)
|
|
{
|
|
Buffer session_id2 = { 0 };
|
|
Identity *id;
|
|
Key *key;
|
|
AuthenticationConnection *ac;
|
|
char *comment;
|
|
uint8_t retval = 0;
|
|
uid_t uid = getpwnam(ruser)->pw_uid;
|
|
|
|
OpenSSL_add_all_digests();
|
|
pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename);
|
|
|
|
if ((ac = ssh_get_authentication_connection(uid))) {
|
|
pamsshagentauth_verbose("Contacted ssh-agent of user %s (%u)", ruser, uid);
|
|
for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2))
|
|
{
|
|
if(key != NULL) {
|
|
id = pamsshagentauth_xcalloc(1, sizeof(*id));
|
|
id->key = key;
|
|
id->filename = comment;
|
|
id->ac = ac;
|
|
if(userauth_pubkey_from_id(ruser, id, &session_id2)) {
|
|
retval = 1;
|
|
}
|
|
pamsshagentauth_xfree(id->filename);
|
|
pamsshagentauth_key_free(id->key);
|
|
pamsshagentauth_xfree(id);
|
|
if(retval == 1)
|
|
break;
|
|
}
|
|
}
|
|
pamsshagentauth_buffer_free(&session_id2);
|
|
ssh_close_authentication_connection(ac);
|
|
}
|
|
else {
|
|
pamsshagentauth_verbose("No ssh-agent could be contacted");
|
|
}
|
|
/* pamsshagentauth_xfree(session_id2); */
|
|
EVP_cleanup();
|
|
return retval;
|
|
}
|