summaryrefslogtreecommitdiffstats
path: root/kdesu/kdesud/handler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kdesu/kdesud/handler.cpp')
-rw-r--r--kdesu/kdesud/handler.cpp512
1 files changed, 0 insertions, 512 deletions
diff --git a/kdesu/kdesud/handler.cpp b/kdesu/kdesud/handler.cpp
deleted file mode 100644
index 2a744b217..000000000
--- a/kdesu/kdesud/handler.cpp
+++ /dev/null
@@ -1,512 +0,0 @@
-/*
- * This file is part of the KDE project, module tdesu.
- * Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
- *
- * handler.cpp: A connection handler for tdesud.
- */
-
-
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <unistd.h>
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#include <tqcstring.h>
-
-#include <kdebug.h>
-#include <tdesu/su.h>
-#include <tdesu/ssh.h>
-
-#include "handler.h"
-#include "repo.h"
-#include "lexer.h"
-#include "secure.h"
-
-
-// Global repository
-extern Repository *repo;
-void tdesud_cleanup();
-
-ConnectionHandler::ConnectionHandler(int fd)
- : SocketSecurity(fd), m_exitCode(0), m_hasExitCode(false), m_needExitCode(false), m_pid(0)
-{
- m_Fd = fd;
- m_Priority = 50;
- m_Scheduler = SuProcess::SchedNormal;
-}
-
-ConnectionHandler::~ConnectionHandler()
-{
- m_Buf.fill('x');
- m_Pass.fill('x');
- close(m_Fd);
-}
-
-/*
- * Handle a connection: make sure we don't block
- */
-
-int ConnectionHandler::handle()
-{
- int ret, nbytes;
-
- // Add max 100 bytes to connection buffer
-
- char tmpbuf[100];
- nbytes = recv(m_Fd, tmpbuf, 99, 0);
-
- if (nbytes < 0)
- {
- if (errno == EINTR)
- return 0;
- // read error
- return -1;
- } else if (nbytes == 0)
- {
- // eof
- return -1;
- }
- tmpbuf[nbytes] = '\000';
-
- if (m_Buf.length()+nbytes > 1024)
- {
- kdWarning(1205) << "line too long";
- return -1;
- }
-
- m_Buf.append(tmpbuf);
- memset(tmpbuf, 'x', nbytes);
-
- // Do we have a complete command yet?
- int n;
- TQCString newbuf;
- while ((n = m_Buf.find('\n')) != -1)
- {
- newbuf = m_Buf.left(n+1);
- m_Buf.fill('x', n+1);
- m_Buf.remove(0, n+1);
- ret = doCommand(newbuf);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
-TQCString ConnectionHandler::makeKey(int _namespace, TQCString s1,
- TQCString s2, TQCString s3)
-{
- TQCString res;
- res.setNum(_namespace);
- res += "*";
- res += s1 + "*" + s2 + "*" + s3;
- return res;
-}
-
-void ConnectionHandler::sendExitCode()
-{
- if (!m_needExitCode)
- return;
- TQCString buf;
- buf.setNum(m_exitCode);
- buf.prepend("OK ");
- buf.append("\n");
-
- send(m_Fd, buf.data(), buf.length(), 0);
-}
-
-void ConnectionHandler::respond(int ok, TQCString s)
-{
- TQCString buf;
-
- switch (ok) {
- case Res_OK:
- buf = "OK";
- break;
- case Res_NO:
- default:
- buf = "NO";
- break;
- }
-
- if (!s.isEmpty())
- {
- buf += ' ';
- buf += s;
- }
-
- buf += '\n';
-
- send(m_Fd, buf.data(), buf.length(), 0);
-}
-
-/*
- * Parse and do one command. On a parse error, return -1. This will
- * close the socket in the main accept loop.
- */
-
-int ConnectionHandler::doCommand(TQCString buf)
-{
- if ((uid_t) peerUid() != getuid())
- {
- kdWarning(1205) << "Peer uid not equal to me\n";
- kdWarning(1205) << "Peer: " << peerUid() << " Me: " << getuid() << endl;
- return -1;
- }
-
- TQCString key, command, pass, name, user, value, env_check;
- Data_entry data;
-
- Lexer *l = new Lexer(buf);
- int tok = l->lex();
- switch (tok)
- {
- case Lexer::Tok_pass: // "PASS password:string timeout:int\n"
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- m_Pass.fill('x');
- m_Pass = l->lval();
- tok = l->lex();
- if (tok != Lexer::Tok_num)
- goto parse_error;
- m_Timeout = l->lval().toInt();
- if (l->lex() != '\n')
- goto parse_error;
- if (m_Pass.isNull())
- m_Pass = "";
- kdDebug(1205) << "Password set!\n";
- respond(Res_OK);
- break;
-
- case Lexer::Tok_host: // "HOST host:string\n"
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- m_Host = l->lval();
- if (l->lex() != '\n')
- goto parse_error;
- kdDebug(1205) << "Host set to " << m_Host << endl;
- respond(Res_OK);
- break;
-
- case Lexer::Tok_prio: // "PRIO priority:int\n"
- tok = l->lex();
- if (tok != Lexer::Tok_num)
- goto parse_error;
- m_Priority = l->lval().toInt();
- if (l->lex() != '\n')
- goto parse_error;
- kdDebug(1205) << "priority set to " << m_Priority << endl;
- respond(Res_OK);
- break;
-
- case Lexer::Tok_sched: // "SCHD scheduler:int\n"
- tok = l->lex();
- if (tok != Lexer::Tok_num)
- goto parse_error;
- m_Scheduler = l->lval().toInt();
- if (l->lex() != '\n')
- goto parse_error;
- kdDebug(1205) << "Scheduler set to " << m_Scheduler << endl;
- respond(Res_OK);
- break;
-
- case Lexer::Tok_exec: // "EXEC command:string user:string [options:string (env:string)*]\n"
- {
- TQCString options;
- QCStringList env;
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- command = l->lval();
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- user = l->lval();
- tok = l->lex();
- if (tok != '\n')
- {
- if (tok != Lexer::Tok_str)
- goto parse_error;
- options = l->lval();
- tok = l->lex();
- while (tok != '\n')
- {
- if (tok != Lexer::Tok_str)
- goto parse_error;
- TQCString env_str = l->lval();
- env.append(env_str);
- if (strncmp(env_str, "DESKTOP_STARTUP_ID=", strlen("DESKTOP_STARTUP_ID=")) != 0)
- env_check += "*"+env_str;
- tok = l->lex();
- }
- }
-
- TQCString auth_user;
- if ((m_Scheduler != SuProcess::SchedNormal) || (m_Priority > 50))
- auth_user = "root";
- else
- auth_user = user;
- key = makeKey(2, m_Host, auth_user, command);
- // We only use the command if the environment is the same.
- if (repo->find(key) == env_check)
- {
- key = makeKey(0, m_Host, auth_user, command);
- pass = repo->find(key);
- }
- if (pass.isNull()) // isNull() means no password, isEmpty() can mean empty password
- {
- if (m_Pass.isNull())
- {
- respond(Res_NO);
- break;
- }
- data.value = env_check;
- data.timeout = m_Timeout;
- key = makeKey(2, m_Host, auth_user, command);
- repo->add(key, data);
- data.value = m_Pass;
- data.timeout = m_Timeout;
- key = makeKey(0, m_Host, auth_user, command);
- repo->add(key, data);
- pass = m_Pass;
- }
-
- // Execute the command asynchronously
- kdDebug(1205) << "Executing command: " << command << endl;
- pid_t pid = fork();
- if (pid < 0)
- {
- kdDebug(1205) << "fork(): " << strerror(errno) << endl;
- respond(Res_NO);
- break;
- } else if (pid > 0)
- {
- m_pid = pid;
- respond(Res_OK);
- break;
- }
-
- // Ignore SIGCHLD because "class SuProcess" needs waitpid()
- signal(SIGCHLD, SIG_DFL);
-
- int ret;
- if (m_Host.isEmpty())
- {
- SuProcess proc;
- proc.setCommand(command);
- proc.setUser(user);
- if (options.contains('x'))
- proc.setXOnly(true);
- if (options.contains('f'))
- proc.setDCOPForwarding(true);
- proc.setPriority(m_Priority);
- proc.setScheduler(m_Scheduler);
- proc.setEnvironment(env);
- ret = proc.exec(pass.data());
- } else
- {
- SshProcess proc;
- proc.setCommand(command);
- proc.setUser(user);
- proc.setHost(m_Host);
- ret = proc.exec(pass.data());
- }
-
- kdDebug(1205) << "Command completed: " << command << endl;
- _exit(ret);
- }
-
- case Lexer::Tok_delCmd: // "DEL command:string user:string\n"
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- command = l->lval();
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- user = l->lval();
- if (l->lex() != '\n')
- goto parse_error;
- key = makeKey(0, m_Host, user, command);
- if (repo->remove(key) < 0) {
- kdDebug(1205) << "Unknown command: " << command << endl;
- respond(Res_NO);
- }
- else {
- kdDebug(1205) << "Deleted command: " << command << ", user = "
- << user << endl;
- respond(Res_OK);
- }
- break;
-
- case Lexer::Tok_delVar: // "DELV name:string \n"
- {
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- name = l->lval();
- tok = l->lex();
- if (tok != '\n')
- goto parse_error;
- key = makeKey(1, name);
- if (repo->remove(key) < 0)
- {
- kdDebug(1205) << "Unknown name: " << name << endl;
- respond(Res_NO);
- }
- else {
- kdDebug(1205) << "Deleted name: " << name << endl;
- respond(Res_OK);
- }
- break;
- }
-
- case Lexer::Tok_delGroup: // "DELG group:string\n"
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- name = l->lval();
- if (repo->removeGroup(name) < 0)
- {
- kdDebug(1205) << "No keys found under group: " << name << endl;
- respond(Res_NO);
- }
- else
- {
- kdDebug(1205) << "Removed all keys under group: " << name << endl;
- respond(Res_OK);
- }
- break;
-
- case Lexer::Tok_delSpecialKey: // "DELS special_key:string\n"
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- name = l->lval();
- if (repo->removeSpecialKey(name) < 0)
- respond(Res_NO);
- else
- respond(Res_OK);
- break;
-
- case Lexer::Tok_set: // "SET name:string value:string group:string timeout:int\n"
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- name = l->lval();
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- data.value = l->lval();
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- data.group = l->lval();
- tok = l->lex();
- if (tok != Lexer::Tok_num)
- goto parse_error;
- data.timeout = l->lval().toInt();
- if (l->lex() != '\n')
- goto parse_error;
- key = makeKey(1, name);
- repo->add(key, data);
- kdDebug(1205) << "Stored key: " << key << endl;
- respond(Res_OK);
- break;
-
- case Lexer::Tok_get: // "GET name:string\n"
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- name = l->lval();
- if (l->lex() != '\n')
- goto parse_error;
- key = makeKey(1, name);
- kdDebug(1205) << "Request for key: " << key << endl;
- value = repo->find(key);
- if (!value.isEmpty())
- respond(Res_OK, value);
- else
- respond(Res_NO);
- break;
-
- case Lexer::Tok_getKeys: // "GETK groupname:string\n"
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- name = l->lval();
- if (l->lex() != '\n')
- goto parse_error;
- kdDebug(1205) << "Request for group key: " << name << endl;
- value = repo->findKeys(name);
- if (!value.isEmpty())
- respond(Res_OK, value);
- else
- respond(Res_NO);
- break;
-
- case Lexer::Tok_chkGroup: // "CHKG groupname:string\n"
- tok = l->lex();
- if (tok != Lexer::Tok_str)
- goto parse_error;
- name = l->lval();
- if (l->lex() != '\n')
- goto parse_error;
- kdDebug(1205) << "Checking for group key: " << name << endl;
- if ( repo->hasGroup( name ) < 0 )
- respond(Res_NO);
- else
- respond(Res_OK);
- break;
-
- case Lexer::Tok_ping: // "PING\n"
- tok = l->lex();
- if (tok != '\n')
- goto parse_error;
- respond(Res_OK);
- break;
-
- case Lexer::Tok_exit: // "EXIT\n"
- tok = l->lex();
- if (tok != '\n')
- goto parse_error;
- m_needExitCode = true;
- if (m_hasExitCode)
- sendExitCode();
- break;
-
- case Lexer::Tok_stop: // "STOP\n"
- tok = l->lex();
- if (tok != '\n')
- goto parse_error;
- kdDebug(1205) << "Stopping by command" << endl;
- respond(Res_OK);
- tdesud_cleanup();
- exit(0);
-
- default:
- kdWarning(1205) << "Unknown command: " << l->lval() << endl;
- respond(Res_NO);
- goto parse_error;
- }
-
- delete l;
- return 0;
-
-parse_error:
- kdWarning(1205) << "Parse error" << endl;
- delete l;
- return -1;
-}
-
-
-