मेरे पास एक प्रक्रिया है जो रूट के रूप में चल रहे डेमॉन द्वारा शुरू होती है, अब मैं इस प्रक्रिया के विशेषाधिकारों को आपके औसत उपयोगकर्ता के "डाउनग्रेड" करना चाहता हूं। क्या यह संभव है? यदि हाँ तो कैसे?
पुनश्च: एक मैक पर यूनिक्स चल रहा है
मेरे पास एक प्रक्रिया है जो रूट के रूप में चल रहे डेमॉन द्वारा शुरू होती है, अब मैं इस प्रक्रिया के विशेषाधिकारों को आपके औसत उपयोगकर्ता के "डाउनग्रेड" करना चाहता हूं। क्या यह संभव है? यदि हाँ तो कैसे?
पुनश्च: एक मैक पर यूनिक्स चल रहा है
जवाबों:
इस प्रक्रिया को स्वयं सेतु (2) पर कॉल करना होगा। यदि आप पहले से ही नहीं हैं, तो आपको इसे चुरोट (8) के अंदर चलाने की भी जांच करनी चाहिए। जहां तक मुझे पता है, किसी अन्य प्रक्रिया के यूआईडी को बदलने के लिए रूट का कोई रास्ता नहीं है।
यदि आप इसे रूट के रूप में चला रहे हैं, तो यह पोर्ट्स को बाइंड करने के लिए है, मैं इसे उच्च पोर्ट पर एक सामान्य उपयोगकर्ता के रूप में चलाने का सुझाव देता हूं और ओएस एक्स पर आईपीएफडब्ल्यू (8) का उपयोग करते हुए पोर्ट 80/443 / इत्यादि को उच्च पोर्ट पर भेज सकता हूं:
http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx
setuid()
अकेले फोन करना बिल्कुल पर्याप्त नहीं है।
sudo tcpdump -Z
अपनी स्वयं की प्रक्रिया के मूल विशेषाधिकारों को छोड़ने के लिए initgroups (3), setgid (2) और setuid (2) का उपयोग करता है।
# code taken from:
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c
/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
username,
(unsigned long)pw->pw_uid,
(unsigned long)pw->pw_gid,
pcap_strerror(errno));
exit(1);
}
...
}
initgroups
, setgid
, setuid
(पिछले!) ठीक यूनिक्स पर सही प्रतिमान है, और हमेशा पालन किया जाना चाहिए। इसके अलावा, एक जिम्मेदार "ड्रॉपरोट" फ़ंक्शन यह जांचता है कि इसका यूआईडी और जीआईडी वास्तव में सेट किया गया है, भले ही सभी तीन प्राथमिक कार्यों ने सफलता लौटा दी हो।
आप अन्य उपयोगकर्ताओं के रूप में कमांड चला सकते हैं su
:
su USERNAME -c COMMAND
COMMAND
गिराए गए विशेषाधिकारों के साथ चलेगा USER
।
ध्यान दें, डिफ़ॉल्ट रूप से, su
कमांड चलाने के लिए लक्ष्य उपयोगकर्ता के शेल दुभाषिया का उपयोग करेगा। इसके विपरीत, का डिफ़ॉल्ट व्यवहार एक स्टैंडअलोन प्रोग्राम के रूप में व्यवहार करना sudo
है COMMAND
, जो वर्तमान वातावरण को चलाता है। बेशक इन डिफ़ॉल्ट व्यवहारों को विभिन्न स्विच और पर्यावरण चर के साथ बदला जा सकता है।
su
यदि USERNAME के पास कोई शेल परिभाषित (या /bin/false
) नहीं है, जबकि sudo काम करता है तो ऐसा नहीं लगता है ।
su
उसे प्रतिबिंबित करेगा। हालांकि, कोई हमेशा -s
स्विच का उपयोग करके ओवरराइड कर सकता है । ध्यान दें कि इसका उद्देश्य su
किसी दिए गए उपयोगकर्ता के व्यवहार की नकल करना है - जो आमतौर पर उसके खोल से प्रभावित होता है। इसके विपरीत, sudo
(डिफ़ॉल्ट रूप से) लक्ष्य उपयोगकर्ता की शेल सेटिंग को अनदेखा करेगा।
विशेषाधिकार छोड़ने के लिए, आपको ड्रॉप करने के लिए एक गैर-रूट उपयोगकर्ता की आवश्यकता होती है। फिर यह उस उपयोगकर्ता के लिए स्विच करने की बात है:
#define UNPRIV_UID 48
#define UNPRIV_GID 48
if (getuid() == 0) { // we are root
// setting UID/GID requires root privileges, so if you don't set
// the GID first, you won't be able to do it at all.
if (setgid(UNPRIV_GID)!=0) die("Failed to set nonroot GID");
if (setuid(UNPRIV_UID)!=0) die("Failed to set nonroot UID");
}
ASSERT(getuid() != 0);
ध्यान दें कि यह प्रोग्राम के भीतर ही किया जाता है, बजाय एक रैपर स्क्रिप्ट के। कई कार्यक्रमों में कुछ विशिष्ट उद्देश्य के लिए रूट विशेषाधिकार की आवश्यकता होती है (उदाहरण के लिए एक कम संख्या वाले पोर्ट से बांधने के लिए), लेकिन उसके बाद रूट की आवश्यकता नहीं है। तो ये प्रोग्राम रूट के रूप में शुरू हो जाएगा, लेकिन एक बार विशेषाधिकारों को छोड़ दें, क्योंकि अब उनकी आवश्यकता नहीं है।
यदि आपको रूट विशेषाधिकारों की आवश्यकता नहीं है, तो बस इसे रूट के रूप में न चलाएं। उदाहरण के लिए:
# Change this:
myprog -C /my/config/file
# To this:
sudo -u someuser myprog -C /my/config/file
# Or this
su someuser -c "myprog -C /my/config/file"
setuid
समारोह केवल सेट प्रभावी यूआईडी, नहीं असली यूआईडी। setreuid
यदि आप प्रक्रिया को विशेषाधिकार प्राप्त करने में सक्षम नहीं होना चाहते हैं तो आपको इसका उपयोग करना चाहिए । (और उपरोक्त कोड पूरक समूह विशेषाधिकारों के साथ सौदा नहीं करता है। यह केवल ज्यादातर विश्वसनीय कोड लॉन्च करने के लिए उपयुक्त है।)
setuid()
डेविड वास्तव में, वास्तविक और सहेजे गए उपयोगकर्ता सेट करता है; आप के बारे में सोच हो सकती है seteuid()
। सभी प्रणालियों में नहीं है setreuid()
, इसलिए इसका हर जगह उपयोग नहीं किया जा सकता है। सटीक शब्दार्थ setuid()
जटिल हैं, लेकिन यदि आपके पास यूरोप 0 है, तो आप सभी पारंपरिक उपयोगकर्ता आईडी विशेषाधिकारों को छोड़ सकेंगे setuid()
। इस जवाब में सबसे बड़ी चूक थी जिसने है initgroups
या setgroups
के रूप में भी बुलाया जाना चाहिए setgid
और setuid
, और कहा कि अधिक गहन दावे अंत में किया जाना चाहिए।
यदि आप एक अलग निष्पादन योग्य कार्य कर रहे हैं, यानी आप कॉल कर रहे हैं execve
या exec
फ़ंक्शन का एक और कार्य, शायद अप्रत्यक्ष रूप से किसी फ़ंक्शन के माध्यम से system
या जैसे popen
, और बच्चे की प्रक्रिया शुरू से विशेषाधिकारों के बिना चलनी चाहिए, तो सबसे आसान तरीका एक प्राप्त करना है खोल शामिल है, और कॉल करें su
। यहां बताया गया है कि पर्ल में कोड कैसा दिख सकता है, इसके लिए आवश्यक उद्धरण दिखाते हुए:
$shell_command = quotemeta($path_to_executable) . " --option";
$shell_command =~ s/'/'\\''/; # protect single quotes for the use as argument to su
$su_command = sprintf("su -c '%s' %s", $shell_command, quotemeta($user_name));
open(PIPE, "$su_command |") or die;
यदि बाल प्रक्रिया को मूल के रूप में शुरू करने की आवश्यकता है, लेकिन बाद में विशेषाधिकारों को छोड़ दें, तो इस उत्तर में कोड देखें , जो दिखाता है कि किसी प्रक्रिया में विशेषाधिकारों को कैसे अपग्रेड किया जाए।