/*
** send.c - Format and send IDENT protocol replies.
**
** Copyright (c) 1997 Peter Eriksson <pen@lysator.liu.se>
**
** This program is free software; you can redistribute it and/or
** modify it as you wish - as long as you don't claim that you wrote
** it.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <stdio.h>
#include <unistd.h>
#include <syslog.h>
#include <pwd.h>

#include "pidentd.h"

int uidonly_flag = 0;
int noident_flag = 0;

char *charset = NULL;
char *opsys = "UNIX";


void
send_error(int fd, int l_port, int r_port, const char *what)
{
    char buf[1024];
    
    sprintf(buf, "%d , %d : ERROR : %s\r\n", l_port, r_port, what);
    s_write(fd, buf, strlen(buf));
}



static int
check_noident(char *dir)
{
    char buf[2048];
    int len;

    
    if (dir == NULL || strlen(dir) > 1024)
	return -1;

    len = strlen(dir);
    memcpy(buf, dir, len);
    if (len > 0 && buf[len-1] != '/')
	buf[len++] = '/';
    strcpy(buf+len, ".noident");

    if (access(buf, F_OK) == 0)
	return 1;
    else
	return 0;
}


void
send_result(int fd, struct kernel *kp)
{
    char buf[1024], pbuf[256];
    struct passwd pwb, *pp = NULL;
    int uid;


    if (debug)
	fprintf(stderr, "send_result(%d) - ruid = %d, euid = %d\n",
		fd, kp->ruid, kp->euid);
    
    if (kp->ruid < 0)
	uid = kp->euid;
    else
	uid = kp->ruid;

    if (!uidonly_flag || noident_flag)
	(void) s_getpwuid_r(uid, &pwb, pbuf, sizeof(pbuf), &pp);

    if (noident_flag && pp && check_noident(pp->pw_dir) == 1)
    {
	syslog(LOG_INFO, "User %s elected to use .noident", pp->pw_name);
	
	send_error(fd,
		   ntohs(kp->local.sin_port),
		   ntohs(kp->remote.sin_port),
		   "HIDDEN-USER");
	return;
    }

#ifdef HAVE_LIBDES
    if (encrypt_flag)
    {
	char buffer[33];

	pdes_encrypt(kp, buffer);
	sprintf(buf, "%d , %d : USERID : OTHER%s%s :%s\r\n",
		ntohs(kp->local.sin_port),
		ntohs(kp->remote.sin_port),
		charset ? " , " : "",
		charset ? charset : "",
		buffer);
    }
    else
#endif
	
    if (!uidonly_flag && pp && strlen(pp->pw_name) < sizeof(buf)-128)
    {
	sprintf(buf, "%d , %d : USERID : %s%s%s :%s\r\n",
		ntohs(kp->local.sin_port),
		ntohs(kp->remote.sin_port),
		opsys,
		charset ? " , " : "",
		charset ? charset : "",
		pp->pw_name);
    }
    else
    {
	sprintf(buf, "%d , %d : USERID : OTHER :%d\r\n",
		ntohs(kp->local.sin_port),
		ntohs(kp->remote.sin_port),
		uid);
    }
    
    s_write(fd, buf, strlen(buf));
}



void
send_version(int fd)
{
    char buf[1024];
    
    sprintf(buf, "0 , 0 : X-VERSION : pidentd %s for %s (%s %s)\r\n",
            server_version,
            osinfo_build, __DATE__, __TIME__);

    s_write(fd, buf, strlen(buf));
}
