source: source/ariba/utility/transport/tcpip/protlib/setuid.cpp@ 10075

Last change on this file since 10075 was 9686, checked in by mies, 14 years ago

put protlib doc to protlib module

File size: 5.4 KB
Line 
1/// ----------------------------------------*- mode: C++; -*--
2/// @file setuid.cpp
3/// Change effective user ID in a thread-safe way.
4/// ----------------------------------------------------------
5/// $Id: setuid.cpp 2549 2007-04-02 22:17:37Z bless $
6/// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/setuid.cpp $
7// ===========================================================
8//
9// Copyright (C) 2005-2007, all rights reserved by
10// - Institute of Telematics, Universitaet Karlsruhe (TH)
11//
12// More information and contact:
13// https://projekte.tm.uka.de/trac/NSIS
14//
15// This program is free software; you can redistribute it and/or modify
16// it under the terms of the GNU General Public License as published by
17// the Free Software Foundation; version 2 of the License
18//
19// This program is distributed in the hope that it will be useful,
20// but WITHOUT ANY WARRANTY; without even the implied warranty of
21// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22// GNU General Public License for more details.
23//
24// You should have received a copy of the GNU General Public License along
25// with this program; if not, write to the Free Software Foundation, Inc.,
26// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27//
28// ===========================================================
29/** @ingroup protlib
30 *
31 * Thread-safe setuid support for linux.
32 * Change effective user ID in a thread-safe way.
33 *
34 * tsdb::init() must be called before calling setuid::init().
35 */
36
37#include <sys/types.h>
38#include <unistd.h>
39#include <errno.h>
40#include <string.h>
41
42#include "setuid.h"
43#include "threadsafe_db.h"
44#include "cleanuphandler.h"
45#include "logfile.h"
46
47
48namespace protlib {
49
50/** @addtogroup protlib
51 * @{
52 */
53
54 using namespace log;
55
56void setuid::init() {
57 if (is_init) {
58 Log(ERROR_LOG,LOG_CRIT, "setuid", "Tried to initialize setuid although already initialized.");
59 } else {
60 pthread_mutex_init(&mutex,NULL);
61 count = 0;
62 file_userid = ::geteuid();
63 real_userid = ::getuid();
64 is_setuid = (real_userid!=file_userid);
65 file_username = tsdb::get_username(file_userid);
66 real_username = tsdb::get_username(real_userid);
67 is_init = true;
68 if (is_setuid) {
69 Log(INFO_LOG,LOG_CRIT, "setuid", "Setuid-bit is set, euid is " << file_userid << " " << file_username << ", realuid is " << real_userid << " " << real_username << ". Turning off setuid as soon as possible");
70 count = 1;
71 off();
72 } else {
73 Log(INFO_LOG,LOG_CRIT, "setuid", "Setuid-bit is not set or euid and ruid are equal. setuid::on() and setuid::off() will do nothing");
74 } // end if is_setuid
75 } // end if is_init
76} // end init
77
78void setuid::end() {
79 if (is_init) {
80 is_init = false;
81 pthread_mutex_destroy(&mutex);
82 count = 0;
83 // turn off setuid
84 if (is_setuid) {
85 Log(INFO_LOG,LOG_CRIT, "setuid", "setuid::end() turn off setuid. Switching (maybe permamently) to " << real_userid << " " << real_username << " using setuid()");
86 ::setuid(real_userid);
87 } // end if is_setuid
88 } else {
89 Log(ERROR_LOG,LOG_CRIT, "setuid", "Tried to end setuid although not initialized.");
90 } // end if is_init
91} // end end
92
93void setuid::on() {
94 if (is_setuid) {
95 if (is_init) {
96 pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
97 if (count==0) {
98 Log(INFO_LOG,LOG_CRIT, "setuid", "setuid::on(): setting euid to " << file_userid << " " << file_username);
99 int status;
100 #ifdef _POSIX_SAVED_IDS
101 status = seteuid(file_userid);
102 #else
103 status = setreuid(real_userid,file_userid);
104 #endif
105 if (status<0) {
106 Log(ERROR_LOG,LOG_ALERT, "setuid", "setuid::on(): error " << strerror(errno));
107 } else count++;
108 } else {
109 Log(INFO_LOG,LOG_CRIT, "setuid", "setuid::on(): setuid already on");
110 count++;
111 } // end if count
112 pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
113 } else {
114 Log(ERROR_LOG,LOG_CRIT, "setuid", "Tried to use setuid although not initialized.");
115 } // end if is_init
116 } // end if is_setuid
117} // end on
118
119void setuid::off() {
120 if (is_setuid) {
121 if (is_init) {
122 pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
123 if (count==1) {
124 int status;
125 #ifdef _POSIX_SAVED_IDS
126 status = seteuid(real_userid);
127 #else
128 status = setreuid(file_userid,real_userid);
129 #endif
130 if (status<0) {
131 Log(ERROR_LOG,LOG_ALERT, "setuid", "setuid::off(): error " << strerror(errno));
132 } else {
133 count = 0;
134 Log(INFO_LOG,LOG_CRIT, "setuid", "setuid::off(): set euid to " << real_userid << " " << real_username);
135 } // end if count
136 } else if (count==0) {
137 Log(INFO_LOG,LOG_CRIT, "setuid", "setuid::off(): setuid already off");
138 } else {
139 Log(INFO_LOG,LOG_CRIT, "setuid", "setuid::off(): setuid still on");
140 count--;
141 } // end if count
142 pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
143 } else {
144 Log(ERROR_LOG,LOG_CRIT, "setuid", "Tried to use setuid although not initialized.");
145 } // end if is_init
146 } // end if is_setuid
147} // end off
148
149bool setuid::is_init = false;
150
151pthread_mutex_t setuid::mutex =
152#ifdef _DEBUG
153 PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
154#else
155 PTHREAD_MUTEX_INITIALIZER;
156#endif
157
158uint32 setuid::count = 0;
159
160uid_t setuid::file_userid = 65534;
161
162string setuid::file_username = "nobody";
163
164uid_t setuid::real_userid = 65534;
165
166string setuid::real_username = "nobody";
167
168bool setuid::is_setuid = true; // important!
169
170//@}
171
172} // end namespace protlib
Note: See TracBrowser for help on using the repository browser.