Ejemplo n.º 1
0
int xio_errhandler(Display *)
{
    kdError(1205) << "Fatal IO error, exiting...\n";
    kdesud_cleanup();
    exit(1);
    return 1;  //silence compilers
}
Ejemplo n.º 2
0
int ConnectionHandler::doCommand(QCString buf)
{
    if((uid_t)peerUid() != getuid())
    {
        kdWarning(1205) << "Peer uid not equal to me\n";
        kdWarning(1205) << "Peer: " << peerUid() << " Me: " << getuid() << endl;
        return -1;
    }

    QCString 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"
        {
            QCString options;
            KStringList 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;
                    QCString 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();
                }
            }

            QCString auth_user;
            if((m_Scheduler != SuProcess::SchedNormal) || (m_Priority > 50))
                auth_user = "******";
            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 = "******"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);
            kdesud_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;
}
Ejemplo n.º 3
0
int main(int argc, char *argv[])
{
    KAboutData aboutData("kdesud", I18N_NOOP("KDE su daemon"),
                         Version, I18N_NOOP("Daemon used by kdesu"),
                         KAboutData::License_Artistic,
                         "Copyright (c) 1999,2000 Geert Jansen");
    aboutData.addAuthor("Geert Jansen", I18N_NOOP("Author"),
                        "*****@*****.**", "http://www.stack.nl/~geertj/");
    KCmdLineArgs::init(argc, argv, &aboutData);
    KInstance instance(&aboutData);

    // Set core dump size to 0
    struct rlimit rlim;
    rlim.rlim_cur = rlim.rlim_max = 0;
    if (setrlimit(RLIMIT_CORE, &rlim) < 0)
    {
        kdError(1205) << "setrlimit(): " << ERR << "\n";
        exit(1);
    }

    // Create the Unix socket.
    int sockfd = create_socket();
    if (sockfd < 0)
        exit(1);
    if (listen(sockfd, 1) < 0)
    {
        kdError(1205) << "listen(): " << ERR << "\n";
        kdesud_cleanup();
        exit(1);
    }
    int maxfd = sockfd;

    // Ok, we're accepting connections. Fork to the background.
    pid_t pid = fork();
    if (pid == -1)
    {
        kdError(1205) << "fork():" << ERR << "\n";
        kdesud_cleanup();
        exit(1);
    }
    if (pid)
        exit(0);

    // Make sure we exit when the display gets closed.
    int x11Fd = initXconnection();
    maxfd = QMAX(maxfd, x11Fd);

    repo = new Repository;
    QPtrVector<ConnectionHandler> handler;
    handler.setAutoDelete(true);

    pipe(pipeOfDeath);
    maxfd = QMAX(maxfd, pipeOfDeath[0]);

    // Signal handlers
    struct sigaction sa;
    sa.sa_handler = signal_exit;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sigaction(SIGHUP, &sa, 0L);
    sigaction(SIGINT, &sa, 0L);
    sigaction(SIGTERM, &sa, 0L);
    sigaction(SIGQUIT, &sa, 0L);

    sa.sa_handler = sigchld_handler;
    sa.sa_flags = SA_NOCLDSTOP;
    sigaction(SIGCHLD, &sa, 0L);
    sa.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &sa, 0L);

    // Main execution loop

    ksocklen_t addrlen;
    struct sockaddr_un clientname;

    fd_set tmp_fds, active_fds;
    FD_ZERO(&active_fds);
    FD_SET(sockfd, &active_fds);
    FD_SET(pipeOfDeath[0], &active_fds);
    if (x11Fd != -1)
        FD_SET(x11Fd, &active_fds);

    while (1)
    {
        tmp_fds = active_fds;
        if(x11Display)
            XFlush(x11Display);
        if (select(maxfd+1, &tmp_fds, 0L, 0L, 0L) < 0)
        {
            if (errno == EINTR) continue;

            kdError(1205) << "select(): " << ERR << "\n";
            exit(1);
        }
        repo->expire();
        for (int i=0; i<=maxfd; i++)
        {
            if (!FD_ISSET(i, &tmp_fds))
                continue;

            if (i == pipeOfDeath[0])
            {
                char buf[101];
                read(pipeOfDeath[0], buf, 100);
                pid_t result;
                do
                {
                    int status;
                    result = waitpid((pid_t)-1, &status, WNOHANG);
                    if (result > 0)
                    {
                        for(int j=handler.size(); j--;)
                        {
                            if (handler[j] && (handler[j]->m_pid == result))
                            {
                                handler[j]->m_exitCode = WEXITSTATUS(status);
                                handler[j]->m_hasExitCode = true;
                                handler[j]->sendExitCode();
                                handler[j]->m_pid = 0;
                                break;
                            }
                        }
                    }
                }
                while(result > 0);
            }

            if (i == x11Fd)
            {
                // Discard X events
                XEvent event_return;
                if (x11Display)
                    while(XPending(x11Display))
                        XNextEvent(x11Display, &event_return);
                continue;
            }

            if (i == sockfd)
            {
                // Accept new connection
                int fd;
                addrlen = 64;
                fd = accept(sockfd, (struct sockaddr *) &clientname, &addrlen);
                if (fd < 0)
                {
                    kdError(1205) << "accept():" << ERR << "\n";
                    continue;
                }
                if (fd+1 > (int) handler.size())
                    handler.resize(fd+1);
                handler.insert(fd, new ConnectionHandler(fd));
                maxfd = QMAX(maxfd, fd);
                FD_SET(fd, &active_fds);
                continue;
            }

            // handle alreay established connection
            if (handler[i] && handler[i]->handle() < 0)
            {
                handler.remove(i);
                FD_CLR(i, &active_fds);
            }
        }
    }
    kdWarning(1205) << "???\n";
}
Ejemplo n.º 4
0
void signal_exit(int sig)
{
    kdDebug(1205) << "Exiting on signal " << sig << "\n";
    kdesud_cleanup();
    exit(1);
}