Subversion Repositories public

Rev

Rev 100 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 100 Rev 102
Line 1... Line 1...
1
1
2
/// inotify cron daemon user tables implementation
2
/// inotify cron daemon user tables implementation
3
/**
3
/**
4
 * \file usertable.cpp
4
 * \file usertable.cpp
5
 *
5
 *
6
 * inotify cron system
6
 * inotify cron system
7
 *
7
 *
8
 * Copyright (C) 2006, 2007, 2008 Lukas Jelinek, <lukas@aiken.cz>
8
 * Copyright (C) 2006, 2007, 2008 Lukas Jelinek, <lukas@aiken.cz>
9
 *
9
 *
10
 * This program is free software; you can use it, redistribute
10
 * This program is free software; you can use it, redistribute
11
 * it and/or modify it under the terms of the GNU General Public
11
 * it and/or modify it under the terms of the GNU General Public
12
 * License, version 2 (see LICENSE-GPL).
12
 * License, version 2 (see LICENSE-GPL).
13
 *
13
 *
14
 * Credits:
14
 * Credits:
15
 *   David Santinoli (supplementary groups)
15
 *   David Santinoli (supplementary groups)
-
 
16
 *   Boris Lechner (spaces in event-related file names)
16
 *
17
 *
17
 */
18
 */
18
19
19
20
20
#include <pwd.h>
21
#include <pwd.h>
21
#include <syslog.h>
22
#include <syslog.h>
Line 27... Line 28...
27
#include <sys/stat.h>
28
#include <sys/stat.h>
28
#include <cstring>
29
#include <cstring>
29
30
30
#include "usertable.h"
31
#include "usertable.h"
31
#include "incroncfg.h"
32
#include "incroncfg.h"
-
 
33
#include "incrontab.h"
32
34
33
#ifdef IN_DONT_FOLLOW
35
#ifdef IN_DONT_FOLLOW
34
#define DONT_FOLLOW(mask) InotifyEvent::IsType(mask, IN_DONT_FOLLOW)
36
#define DONT_FOLLOW(mask) InotifyEvent::IsType(mask, IN_DONT_FOLLOW)
35
#else // IN_DONT_FOLLOW
37
#else // IN_DONT_FOLLOW
36
#define DONT_FOLLOW(mask) (false)
38
#define DONT_FOLLOW(mask) (false)
Line 76... Line 78...
76
  if (pipe) {
78
  if (pipe) {
77
    char c;
79
    char c;
78
    while (read(m_pPoll[0].fd, &c, 1) > 0) {}
80
    while (read(m_pPoll[0].fd, &c, 1) > 0) {}
79
    m_pPoll[0].revents = 0;
81
    m_pPoll[0].revents = 0;
80
  }
82
  }
81
 
83
82
  // process table management events if any
84
  // process table management events if any
83
  if (m_pPoll[1].revents & POLLIN) {
85
  if (m_pPoll[1].revents & POLLIN) {
84
    ProcessMgmtEvents();
86
    ProcessMgmtEvents();
85
    m_pPoll[1].revents = 0;
87
    m_pPoll[1].revents = 0;
86
  }
88
  }
87
   
89
88
  InotifyEvent evt;
90
  InotifyEvent evt;
89
   
91
90
  for (size_t i=2; i<m_size; i++) {
92
  for (size_t i=2; i<m_size; i++) {
91
   
93
92
    // process events if occurred
94
    // process events if occurred
93
    if (m_pPoll[i].revents & POLLIN) {
95
    if (m_pPoll[i].revents & POLLIN) {
94
      FDUT_MAP::iterator it = m_maps.find(m_pPoll[i].fd);
96
      FDUT_MAP::iterator it = m_maps.find(m_pPoll[i].fd);
95
      if (it != m_maps.end()) {
97
      if (it != m_maps.end()) {
96
        Inotify* pIn = ((*it).second)->GetInotify();
98
        Inotify* pIn = ((*it).second)->GetInotify();
97
        pIn->WaitForEvents(true);
99
        pIn->WaitForEvents(true);
98
       
100
99
        // process events for this object
101
        // process events for this object
100
        while (pIn->GetEvent(evt)) {
102
        while (pIn->GetEvent(evt)) {
101
          ((*it).second)->OnEvent(evt);
103
          ((*it).second)->OnEvent(evt);
102
        }
104
        }
103
      }
105
      }
104
      m_pPoll[i].revents = 0;
106
      m_pPoll[i].revents = 0;
105
    }
107
    }
106
  }
108
  }
107
   
109
108
  return pipe;
110
  return pipe;
109
}
111
}
110
 
112
111
void EventDispatcher::Register(UserTable* pTab)
113
void EventDispatcher::Register(UserTable* pTab)
112
{
114
{
113
  if (pTab != NULL) {
115
  if (pTab != NULL) {
114
    Inotify* pIn = pTab->GetInotify();
116
    Inotify* pIn = pTab->GetInotify();
115
    if (pIn != NULL) {
117
    if (pIn != NULL) {
Line 119... Line 121...
119
        Rebuild();
121
        Rebuild();
120
      }
122
      }
121
    }
123
    }
122
  }
124
  }
123
}
125
}
124
 
126
125
void EventDispatcher::Unregister(UserTable* pTab)
127
void EventDispatcher::Unregister(UserTable* pTab)
126
{
128
{
127
  FDUT_MAP::iterator it = m_maps.find(pTab->GetInotify()->GetDescriptor());
129
  FDUT_MAP::iterator it = m_maps.find(pTab->GetInotify()->GetDescriptor());
128
  if (it != m_maps.end()) {
130
  if (it != m_maps.end()) {
129
    m_maps.erase(it);
131
    m_maps.erase(it);
Line 134... Line 136...
134
void EventDispatcher::Rebuild()
136
void EventDispatcher::Rebuild()
135
{
137
{
136
  // delete old data if exists
138
  // delete old data if exists
137
  if (m_pPoll != NULL)
139
  if (m_pPoll != NULL)
138
    delete[] m_pPoll;
140
    delete[] m_pPoll;
139
   
141
140
  // allocate memory
142
  // allocate memory
141
  m_size = m_maps.size() + 2;
143
  m_size = m_maps.size() + 2;
142
  m_pPoll = new struct pollfd[m_size];
144
  m_pPoll = new struct pollfd[m_size];
143
 
145
144
  // add pipe descriptor
146
  // add pipe descriptor
145
  m_pPoll[0].fd = m_iPipeFd;
147
  m_pPoll[0].fd = m_iPipeFd;
146
  m_pPoll[0].events = POLLIN;
148
  m_pPoll[0].events = POLLIN;
147
  m_pPoll[0].revents = 0;
149
  m_pPoll[0].revents = 0;
148
 
150
149
  // add table management descriptor
151
  // add table management descriptor
150
  m_pPoll[1].fd = m_iMgmtFd;
152
  m_pPoll[1].fd = m_iMgmtFd;
151
  m_pPoll[1].events = POLLIN;
153
  m_pPoll[1].events = POLLIN;
152
  m_pPoll[1].revents = 0;
154
  m_pPoll[1].revents = 0;
153
 
155
154
  // add all inotify descriptors
156
  // add all inotify descriptors
155
  FDUT_MAP::iterator it = m_maps.begin();
157
  FDUT_MAP::iterator it = m_maps.begin();
156
  for (size_t i=2; i<m_size; i++, it++) {
158
  for (size_t i=2; i<m_size; i++, it++) {
157
    m_pPoll[i].fd = (*it).first;
159
    m_pPoll[i].fd = (*it).first;
158
    m_pPoll[i].events = POLLIN;
160
    m_pPoll[i].events = POLLIN;
Line 161... Line 163...
161
}
163
}
162
164
163
void EventDispatcher::ProcessMgmtEvents()
165
void EventDispatcher::ProcessMgmtEvents()
164
{
166
{
165
  m_pIn->WaitForEvents(true);
167
  m_pIn->WaitForEvents(true);
166
 
168
167
  InotifyEvent e;
169
  InotifyEvent e;
168
 
170
169
  while (m_pIn->GetEvent(e)) {
171
  while (m_pIn->GetEvent(e)) {
170
    if (e.GetWatch() == m_pSys) {
172
    if (e.GetWatch() == m_pSys) {
171
      if (e.IsType(IN_DELETE_SELF) || e.IsType(IN_UNMOUNT)) {
173
      if (e.IsType(IN_DELETE_SELF) || e.IsType(IN_UNMOUNT)) {
172
        syslog(LOG_CRIT, "base directory destroyed, exitting");
174
        syslog(LOG_CRIT, "base directory destroyed, exitting");
173
        g_fFinish = true;
175
        g_fFinish = true;
Line 234... Line 236...
234
UserTable::UserTable(EventDispatcher* pEd, const std::string& rUser, bool fSysTable)
236
UserTable::UserTable(EventDispatcher* pEd, const std::string& rUser, bool fSysTable)
235
: m_user(rUser),
237
: m_user(rUser),
236
  m_fSysTable(fSysTable)
238
  m_fSysTable(fSysTable)
237
{
239
{
238
  m_pEd = pEd;
240
  m_pEd = pEd;
239
 
241
240
  m_in.SetNonBlock(true);
242
  m_in.SetNonBlock(true);
241
  m_in.SetCloseOnExec(true);
243
  m_in.SetCloseOnExec(true);
242
}
244
}
243
245
244
UserTable::~UserTable()
246
UserTable::~UserTable()
245
{
247
{
246
  Dispose();
248
  Dispose();
247
}
249
}
248
 
250
249
void UserTable::Load()
251
void UserTable::Load()
250
{
252
{
251
  m_tab.Load(m_fSysTable
253
  m_tab.Load(m_fSysTable
252
      ? IncronTab::GetSystemTablePath(m_user)
254
      ? IncronTab::GetSystemTablePath(m_user)
253
      : IncronTab::GetUserTablePath(m_user));
255
      : IncronTab::GetUserTablePath(m_user));
254
 
256
255
  int cnt = m_tab.GetCount();
257
  int cnt = m_tab.GetCount();
256
  for (int i=0; i<cnt; i++) {
258
  for (int i=0; i<cnt; i++) {
257
    IncronTabEntry& rE = m_tab.GetEntry(i);
259
    IncronTabEntry& rE = m_tab.GetEntry(i);
258
    InotifyWatch* pW = new InotifyWatch(rE.GetPath(), rE.GetMask());
260
    InotifyWatch* pW = new InotifyWatch(rE.GetPath(), rE.GetMask());
259
   
261
260
    // warning only - permissions may change later
262
    // warning only - permissions may change later
261
    if (!(m_fSysTable || MayAccess(rE.GetPath(), DONT_FOLLOW(rE.GetMask()))))
263
    if (!(m_fSysTable || MayAccess(rE.GetPath(), DONT_FOLLOW(rE.GetMask()))))
262
      syslog(LOG_WARNING, "access denied on %s - events will be discarded silently", rE.GetPath().c_str());
264
      syslog(LOG_WARNING, "access denied on %s - events will be discarded silently", rE.GetPath().c_str());
263
   
265
264
    try {
266
    try {
265
      m_in.Add(pW);
267
      m_in.Add(pW);
266
      m_map.insert(IWCE_MAP::value_type(pW, &rE));
268
      m_map.insert(IWCE_MAP::value_type(pW, &rE));
267
    } catch (InotifyException e) {
269
    } catch (InotifyException e) {
268
      if (m_fSysTable)
270
      if (m_fSysTable)
Line 270... Line 272...
270
      else
272
      else
271
        syslog(LOG_ERR, "cannot create watch for user %s: (%i) %s", m_user.c_str(), e.GetErrorNumber(), strerror(e.GetErrorNumber()));
273
        syslog(LOG_ERR, "cannot create watch for user %s: (%i) %s", m_user.c_str(), e.GetErrorNumber(), strerror(e.GetErrorNumber()));
272
      delete pW;
274
      delete pW;
273
    }
275
    }
274
  }
276
  }
275
 
277
276
  m_pEd->Register(this);
278
  m_pEd->Register(this);
277
}
279
}
278
280
279
void UserTable::Dispose()
281
void UserTable::Dispose()
280
{
282
{
281
  m_pEd->Unregister(this);
283
  m_pEd->Unregister(this);
282
 
284
283
  IWCE_MAP::iterator it = m_map.begin();
285
  IWCE_MAP::iterator it = m_map.begin();
284
  while (it != m_map.end()) {
286
  while (it != m_map.end()) {
285
    InotifyWatch* pW = (*it).first;
287
    InotifyWatch* pW = (*it).first;
286
    m_in.Remove(pW);
288
    m_in.Remove(pW);
287
   
289
288
    PROC_MAP::iterator it2 = s_procMap.begin();
290
    PROC_MAP::iterator it2 = s_procMap.begin();
289
    while (it2 != s_procMap.end()) {
291
    while (it2 != s_procMap.end()) {
290
      if ((*it2).second.pWatch == pW) {
292
      if ((*it2).second.pWatch == pW) {
291
        PROC_MAP::iterator it3 = it2;
293
        PROC_MAP::iterator it3 = it2;
292
        it2++;
294
        it2++;
Line 294... Line 296...
294
      }
296
      }
295
      else {
297
      else {
296
        it2++;
298
        it2++;
297
      }
299
      }
298
    }
300
    }
299
   
301
300
    delete pW;
302
    delete pW;
301
    it++;
303
    it++;
302
  }
304
  }
303
 
305
304
  m_map.clear();
306
  m_map.clear();
305
}
307
}
306
 
308
307
void UserTable::OnEvent(InotifyEvent& rEvt)
309
void UserTable::OnEvent(InotifyEvent& rEvt)
308
{
310
{
309
  InotifyWatch* pW = rEvt.GetWatch();
311
  InotifyWatch* pW = rEvt.GetWatch();
310
  IncronTabEntry* pE = FindEntry(pW);
312
  IncronTabEntry* pE = FindEntry(pW);
311
 
313
312
  // no entry found - this shouldn't occur
314
  // no entry found - this shouldn't occur
313
  if (pE == NULL)
315
  if (pE == NULL)
314
    return;
316
    return;
315
 
317
316
  // discard event if user has no access rights to watch path
318
  // discard event if user has no access rights to watch path
317
  if (!(m_fSysTable || MayAccess(pW->GetPath(), DONT_FOLLOW(rEvt.GetMask()))))
319
  if (!(m_fSysTable || MayAccess(pW->GetPath(), DONT_FOLLOW(rEvt.GetMask()))))
318
    return;
320
    return;
319
 
321
320
  std::string cmd;
322
  std::string cmd;
321
  const std::string& cs = pE->GetCmd();
323
  const std::string& cs = pE->GetCmd();
322
  size_t pos = 0;
324
  size_t pos = 0;
323
  size_t oldpos = 0;
325
  size_t oldpos = 0;
324
  size_t len = cs.length();
326
  size_t len = cs.length();
Line 334... Line 336...
334
        if (cs[px] == '@') {          // base path
336
        if (cs[px] == '@') {          // base path
335
          cmd.append(pW->GetPath());
337
          cmd.append(pW->GetPath());
336
          oldpos = pos + 2;
338
          oldpos = pos + 2;
337
        }
339
        }
338
        else if (cs[px] == '#') {     // file name
340
        else if (cs[px] == '#') {     // file name
339
          cmd.append(rEvt.GetName());
341
          cmd.append(IncronTabEntry::GetSafePath(rEvt.GetName()));
340
          oldpos = pos + 2;
342
          oldpos = pos + 2;
341
        }
343
        }
342
        else if (cs[px] == '%') {     // mask symbols
344
        else if (cs[px] == '%') {     // mask symbols
343
          std::string s;
345
          std::string s;
344
          rEvt.DumpTypes(s);
346
          rEvt.DumpTypes(s);
Line 359... Line 361...
359
    }
361
    }
360
    else {
362
    else {
361
      cmd.append(cs.substr(oldpos, pos-oldpos));
363
      cmd.append(cs.substr(oldpos, pos-oldpos));
362
      oldpos = pos + 1;
364
      oldpos = pos + 1;
363
    }
365
    }
364
  }    
366
  }
365
  cmd.append(cs.substr(oldpos));
367
  cmd.append(cs.substr(oldpos));
366
 
368
367
  int argc;
369
  int argc;
368
  char** argv;
370
  char** argv;
369
  if (!PrepareArgs(cmd, argc, argv)) {
371
  if (!PrepareArgs(cmd, argc, argv)) {
370
    syslog(LOG_ERR, "cannot prepare command arguments");
372
    syslog(LOG_ERR, "cannot prepare command arguments");
371
    return;
373
    return;
372
  }
374
  }
373
 
375
374
  if (m_fSysTable)
376
  if (m_fSysTable)
375
    syslog(LOG_INFO, "(system::%s) CMD (%s)", m_user.c_str(), cmd.c_str());
377
    syslog(LOG_INFO, "(system::%s) CMD (%s)", m_user.c_str(), cmd.c_str());
376
  else
378
  else
377
    syslog(LOG_INFO, "(%s) CMD (%s)", m_user.c_str(), cmd.c_str());
379
    syslog(LOG_INFO, "(%s) CMD (%s)", m_user.c_str(), cmd.c_str());
378
 
380
379
  if (pE->IsNoLoop())
381
  if (pE->IsNoLoop())
380
    pW->SetEnabled(false);
382
    pW->SetEnabled(false);
381
 
383
382
  pid_t pid = fork();
384
  pid_t pid = fork();
383
  if (pid == 0) {
385
  if (pid == 0) {
384
   
386
385
    // for system table
387
    // for system table
386
    if (m_fSysTable) {
388
    if (m_fSysTable) {
387
      if (execvp(argv[0], argv) != 0) // exec failed
389
      if (execvp(argv[0], argv) != 0) // exec failed
388
      {
390
      {
389
        syslog(LOG_ERR, "cannot exec process: %s", strerror(errno));
391
        syslog(LOG_ERR, "cannot exec process: %s", strerror(errno));
Line 403... Line 405...
403
    }
405
    }
404
    else {
406
    else {
405
      pd.onDone = NULL;
407
      pd.onDone = NULL;
406
      pd.pWatch = NULL;
408
      pd.pWatch = NULL;
407
    }
409
    }
408
   
410
409
    s_procMap.insert(PROC_MAP::value_type(pid, pd));
411
    s_procMap.insert(PROC_MAP::value_type(pid, pd));
410
  }
412
  }
411
  else {
413
  else {
412
    if (pE->IsNoLoop())
414
    if (pE->IsNoLoop())
413
      pW->SetEnabled(true);
415
      pW->SetEnabled(true);
414
     
416
415
    syslog(LOG_ERR, "cannot fork process: %s", strerror(errno));
417
    syslog(LOG_ERR, "cannot fork process: %s", strerror(errno));
416
  }
418
  }
417
 
419
418
  CleanupArgs(argc, argv);
420
  CleanupArgs(argc, argv);
419
}
421
}
420
422
421
IncronTabEntry* UserTable::FindEntry(InotifyWatch* pWatch)
423
IncronTabEntry* UserTable::FindEntry(InotifyWatch* pWatch)
422
{
424
{
423
  IWCE_MAP::iterator it = m_map.find(pWatch);
425
  IWCE_MAP::iterator it = m_map.find(pWatch);
424
  if (it == m_map.end())
426
  if (it == m_map.end())
425
    return NULL;
427
    return NULL;
426
   
428
427
  return (*it).second;
429
  return (*it).second;
428
}
430
}
429
431
430
bool UserTable::PrepareArgs(const std::string& rCmd, int& argc, char**& argv)
432
bool UserTable::PrepareArgs(const std::string& rCmd, int& argc, char**& argv)
431
{
433
{
432
  if (rCmd.empty())
434
  if (rCmd.empty())
433
    return false;
435
    return false;
434
   
436
435
  StringTokenizer tok(rCmd, ' ', '\\');
437
  StringTokenizer tok(rCmd, ' ', '\\');
436
  std::deque<std::string> args;
438
  std::deque<std::string> args;
437
  while (tok.HasMoreTokens()) {
439
  while (tok.HasMoreTokens()) {
438
    args.push_back(tok.GetNextToken());
440
    args.push_back(tok.GetNextToken());
439
  }
441
  }
440
 
442
441
  if (args.empty())
443
  if (args.empty())
442
    return false;
444
    return false;
443
 
445
444
  argc = (int) args.size();
446
  argc = (int) args.size();
445
  argv = new char*[argc+1];
447
  argv = new char*[argc+1];
446
  argv[argc] = NULL;
448
  argv[argc] = NULL;
447
 
449
448
  for (int i=0; i<argc; i++) {
450
  for (int i=0; i<argc; i++) {
449
    const std::string& s = args[i];
451
    const std::string& s = args[i];
450
    size_t len = s.length();
452
    size_t len = s.length();
451
    argv[i] = new char[len+1];
453
    argv[i] = new char[len+1];
452
    strcpy(argv[i], s.c_str());
454
    strcpy(argv[i], s.c_str());
453
  }
455
  }
454
 
456
455
  return true;
457
  return true;
456
}
458
}
457
459
458
void UserTable::CleanupArgs(int argc, char** argv)
460
void UserTable::CleanupArgs(int argc, char** argv)
459
{
461
{
460
  for (int i=0; i<argc; i++) {
462
  for (int i=0; i<argc; i++) {
461
    delete[] argv[i];
463
    delete[] argv[i];
462
  }
464
  }
463
 
465
464
  delete[] argv;
466
  delete[] argv;
465
}
467
}
466
468
467
void UserTable::FinishDone()
469
void UserTable::FinishDone()
468
{
470
{
Line 474... Line 476...
474
      ProcData_t pd = (*it).second;
476
      ProcData_t pd = (*it).second;
475
      if (pd.onDone != NULL)
477
      if (pd.onDone != NULL)
476
        (*pd.onDone)(pd.pWatch);
478
        (*pd.onDone)(pd.pWatch);
477
      s_procMap.erase(it);
479
      s_procMap.erase(it);
478
    }
480
    }
479
  }  
481
  }
480
}
482
}
481
483
482
bool UserTable::MayAccess(const std::string& rPath, bool fNoFollow) const
484
bool UserTable::MayAccess(const std::string& rPath, bool fNoFollow) const
483
{
485
{
484
  // first, retrieve file permissions
486
  // first, retrieve file permissions
Line 486... Line 488...
486
  int res = fNoFollow
488
  int res = fNoFollow
487
      ? lstat(rPath.c_str(), &st) // don't follow symlink
489
      ? lstat(rPath.c_str(), &st) // don't follow symlink
488
      : stat(rPath.c_str(), &st);
490
      : stat(rPath.c_str(), &st);
489
  if (res != 0)
491
  if (res != 0)
490
    return false; // retrieving permissions failed
492
    return false; // retrieving permissions failed
491
 
493
492
  // file accessible to everyone
494
  // file accessible to everyone
493
  if (st.st_mode & S_IRWXO)
495
  if (st.st_mode & S_IRWXO)
494
    return true;
496
    return true;
495
 
497
496
  // retrieve user data
498
  // retrieve user data
497
  struct passwd* pwd = getpwnam(m_user.c_str());
499
  struct passwd* pwd = getpwnam(m_user.c_str());
498
 
500
499
  // root may always access
501
  // root may always access
500
  if (pwd->pw_uid == 0)
502
  if (pwd->pw_uid == 0)
501
    return true;
503
    return true;
502
 
504
503
  // file accesible to group
505
  // file accessible to group
504
  if (st.st_mode & S_IRWXG) {
506
  if (st.st_mode & S_IRWXG) {
505
   
507
506
    // user's primary group
508
    // user's primary group
507
    if (pwd != NULL && pwd->pw_gid == st.st_gid)
509
    if (pwd != NULL && pwd->pw_gid == st.st_gid)
508
        return true;
510
        return true;
509
   
511
510
    // now check group database
512
    // now check group database
511
    struct group *gr = getgrgid(st.st_gid);
513
    struct group *gr = getgrgid(st.st_gid);
512
    if (gr != NULL) {
514
    if (gr != NULL) {
513
      int pos = 0;
515
      int pos = 0;
514
      const char* un;
516
      const char* un;
Line 517... Line 519...
517
          return true;
519
          return true;
518
        pos++;
520
        pos++;
519
      }
521
      }
520
    }
522
    }
521
  }
523
  }
522
 
524
523
  // file accessible to owner
525
  // file accessible to owner
524
  if (st.st_mode & S_IRWXU) {  
526
  if (st.st_mode & S_IRWXU) {
525
    if (pwd != NULL && pwd->pw_uid == st.st_uid)
527
    if (pwd != NULL && pwd->pw_uid == st.st_uid)
526
      return true;
528
      return true;
527
  }
529
  }
528
 
530
529
  return false; // no access right found
531
  return false; // no access right found
530
}
532
}
531
533
532
void UserTable::RunAsUser(char* const* argv) const
534
void UserTable::RunAsUser(char* const* argv) const
533
{
535
{
Line 537... Line 539...
537
      ||  initgroups(m_user.c_str(),pwd->pw_gid) != 0 // check supplementary groups
539
      ||  initgroups(m_user.c_str(),pwd->pw_gid) != 0 // check supplementary groups
538
      ||  setuid(pwd->pw_uid) != 0)    // check UID
540
      ||  setuid(pwd->pw_uid) != 0)    // check UID
539
  {
541
  {
540
    goto failed;
542
    goto failed;
541
  }
543
  }
542
 
544
543
  if (pwd->pw_uid != 0) {
545
  if (pwd->pw_uid != 0) {
544
    if (clearenv() != 0)
546
    if (clearenv() != 0)
545
      goto failed;
547
      goto failed;
546
     
548
547
    if (    setenv("LOGNAME",   pwd->pw_name,   1) != 0
549
    if (    setenv("LOGNAME",   pwd->pw_name,   1) != 0
548
        ||  setenv("USER",      pwd->pw_name,   1) != 0
550
        ||  setenv("USER",      pwd->pw_name,   1) != 0
549
        ||  setenv("USERNAME",  pwd->pw_name,   1) != 0
551
        ||  setenv("USERNAME",  pwd->pw_name,   1) != 0
550
        ||  setenv("HOME",      pwd->pw_dir,    1) != 0
552
        ||  setenv("HOME",      pwd->pw_dir,    1) != 0
551
        ||  setenv("SHELL",     pwd->pw_shell,  1) != 0
553
        ||  setenv("SHELL",     pwd->pw_shell,  1) != 0
552
        ||  setenv("PATH",      DEFAULT_PATH,   1) != 0)
554
        ||  setenv("PATH",      DEFAULT_PATH,   1) != 0)
553
    {
555
    {
554
      goto failed;
556
      goto failed;
555
    }
557
    }
556
  }
558
  }
557
 
559
558
  execvp(argv[0], argv);  // this may return only on failure
560
  execvp(argv[0], argv);  // this may return only on failure
559
 
561
560
failed:
562
failed:
561
   
563
562
  syslog(LOG_ERR, "cannot exec process: %s", strerror(errno));
564
  syslog(LOG_ERR, "cannot exec process: %s", strerror(errno));
563
  _exit(1);
565
  _exit(1);
564
}
566
}
565
567