owlocalhelper_main.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
00029 *******************************************************************************/
00030 
00035 #include "OW_config.h"
00036 #include "OW_String.hpp"
00037 #include "OW_Array.hpp"
00038 #include "OW_FileSystem.hpp"
00039 #include "OW_Format.hpp"
00040 #include "OW_LocalAuthenticationCommon.hpp"
00041 
00042 #include <unistd.h>
00043 #include <sys/types.h>
00044 #include <pwd.h>
00045 #include <sys/stat.h>
00046 #if defined(OW_HAVE_SYS_TIME_H)
00047 #include <sys/time.h>
00048 #endif
00049 #if defined(OW_HAVE_SYS_RESOURCE_H)
00050 #include <sys/resource.h>
00051 #endif
00052 
00053 #include <cstring>
00054 #include <cstdio>
00055 #include <cerrno>
00056 #include <ctime>
00057 #include <iostream>
00058 
00059 // commands (first line read from stdin):
00060 //   remove - delete one file
00061 //    input: filename w/out the path, cookie
00062 //    output: none
00063 //   initialize - create dir if necessary & remove all old files
00064 //    input: none
00065 //    output: none
00066 //   create - creates a file
00067 //    input: uid, cookie
00068 //    output: absolute pathname
00069 //
00070 // If the operation was successful, 0 (SUCCESS) is the return value.
00071 // If the operation failed, an error message is printed to stderr and the return code is != 0.
00072 
00073 using std::cerr;
00074 using std::endl;
00075 using std::cin;
00076 using std::cout;
00077 using namespace OpenWBEM;
00078 using namespace OpenWBEM::LocalAuthenticationCommon;
00079 
00080 namespace
00081 {
00082 
00083 const char* OWCIMOMD_USER_STR = "owcimomd";
00084 
00085 const int SUCCESS = 0;
00086 
00087 // list of possible error codes.
00088 const int INVALID_USER = 2;
00089 const int NOT_SETUID_ROOT = 3;
00090 const int INVALID_INPUT = 4;
00091 const int REMOVE_FAILED = 5;
00092 const int UNEXPECTED_EXCEPTION = 6;
00093 const int SETRLIMIT_FAILED = 7;
00094 
00095 bool checkRealUser()
00096 {
00097    struct passwd* pw = ::getpwuid(::getuid());
00098    if (pw == 0)
00099    {
00100       perror("owlocalhelper:checkRealUser():getpwuid");
00101       return false;
00102    }
00103    if (strcmp(OWCIMOMD_USER_STR, pw->pw_name) == 0)
00104    {
00105       return true;
00106    }
00107    cerr << "owlocalhelper:checkRealUser(): username is not " << OWCIMOMD_USER_STR << endl;
00108    return false;
00109 }
00110 
00111 // returns true if a line was successfully read
00112 bool getLineFromStdin(String& line)
00113 {
00114    // Use basic_istream::getline() instead of String::getline() so that I can limit the amount of data that is read.
00115 
00116    const int lineBufferSize = 1024;
00117    char buffer[lineBufferSize];
00118    cin.getline(buffer, lineBufferSize, '\n');
00119    int count = cin.gcount();
00120 
00121    // if hit eof
00122    if (!cin && count == 0)
00123    {
00124       cerr << "owlocalhelper:getLineFromStdin(): expected a line, but hit eof." << endl;
00125       return false;
00126    }
00127 
00128    // read a partial line, then hit eof
00129    if (cin.eof())
00130    {
00131       line = buffer;
00132       return true;
00133    }
00134 
00135    // line is longer than the buffer.  This shouldn't happen, and I'll treat it as a fatal error
00136    else if (cin.fail())
00137    {
00138       cerr << "owlocalhelper:getLineFromStdin(): line too long." << endl;
00139       return false;
00140    }
00141 
00142    // successfully read a line
00143    else
00144    {
00145       line = buffer;
00146       return true;
00147    }
00148 }
00149 
00150 int processRemove()
00151 {
00152    String filename;
00153    if (!getLineFromStdin(filename))
00154    {
00155       return INVALID_INPUT;
00156    }
00157 
00158    if (filename.indexOf(OW_FILENAME_SEPARATOR) != String::npos)
00159    {
00160       cerr << "owlocalhelper::processRemove(): filename cannot contain " OW_FILENAME_SEPARATOR << endl;
00161       return INVALID_INPUT;
00162    }
00163 
00164    if (filename.empty())
00165    {
00166       cerr << "owlocalhelper::processRemove(): filename cannot be empty." << endl;
00167       return INVALID_INPUT;
00168    }
00169 
00170    String fullPath = String(LOCAL_AUTH_DIR) + OW_FILENAME_SEPARATOR + filename;
00171    // translate to the real path and recheck the directory
00172    String realPath;
00173    try
00174    {
00175        realPath = FileSystem::Path::realPath(fullPath);
00176    }
00177    catch (FileSystemException& e)
00178    {
00179       cerr << "owlocalhelper::processRemove(): realPath failed: " << e << endl;
00180       return INVALID_INPUT;
00181    }
00182 
00183    String realPathDirname = FileSystem::Path::dirname(realPath);
00184    if (realPath != fullPath || realPathDirname != LOCAL_AUTH_DIR)
00185    {
00186       cerr << "owlocalhelper::processRemove(): real path is not equal. no symlinks allowed in " << fullPath << endl;
00187       return INVALID_INPUT;
00188    }
00189 
00190    String cookie;
00191    if (!getLineFromStdin(cookie))
00192    {
00193       return INVALID_INPUT;
00194    }
00195 
00196    String realCookie = FileSystem::getFileContents(realPath);
00197 
00198    if (realCookie != cookie)
00199    {
00200       cerr << "owlocalhelper::processRemove(): real cookie is not equal, not removing." << endl;
00201       return INVALID_INPUT;
00202    }
00203 
00204    if (!FileSystem::removeFile(realPath))
00205    {
00206       perror(Format("owlocalhelper::processRemove(): failed to remove %1", realPath).c_str());
00207       return REMOVE_FAILED;
00208    }
00209 
00210    return SUCCESS;
00211 }
00212 
00213 int processCreate()
00214 {
00215    // Read the uid from stdin
00216    String uid;
00217    if (!getLineFromStdin(uid))
00218    {
00219       cerr << "owlocalhelper::processCreate(): expected to get the uid" << endl;
00220       return INVALID_INPUT;
00221    }
00222    
00223    // Read a random number from stdin to put in file for client to read
00224    String cookie;
00225    if (!getLineFromStdin(cookie))
00226    {
00227       cerr << "owlocalhelper::processCreate(): expected to get the cookie" << endl;
00228       return INVALID_INPUT;
00229    }
00230 
00231     cout << createFile(uid, cookie) << endl;
00232    
00233    return SUCCESS;
00234 }
00235 
00236 int processStdin()
00237 {
00238    // even though we'll only run if getuid() == owcimomd, we'll still be extremely 
00239    // paranoid about any input we get, since as a setuid binary, we could do a lot
00240    // of damage
00241 
00242    String curLine;
00243     if (!getLineFromStdin(curLine))
00244    {
00245       return INVALID_INPUT;
00246    }
00247 
00248    if (curLine == REMOVE_CMD)
00249    {
00250       return processRemove();
00251    }
00252    else if (curLine == INITIALIZE_CMD)
00253    {
00254       initializeDir();
00255       return SUCCESS;
00256    }
00257    else if (curLine == CREATE_CMD)
00258    {
00259       return processCreate();
00260    }
00261 
00262    return INVALID_INPUT;
00263 }
00264 
00265 } // end unnamed namespace
00266 
00267 
00269 int main(int argc, char* argv[])
00270 {
00271    try
00272    {
00273 
00274       // I want full control over file permissions
00275       ::umask(0);
00276 
00277 #ifdef OW_HAVE_SETRLIMIT
00278       // Be careful to not drop core.
00279       struct rlimit rlim;
00280       rlim.rlim_cur = rlim.rlim_max = 0;
00281       if (setrlimit(RLIMIT_CORE, &rlim) < 0)
00282       {
00283          perror("owlocalhelper::setrlimit failed");
00284          return SETRLIMIT_FAILED;
00285       }
00286 #endif
00287    
00288       // only owcimomd user can run me, but we still have to be careful in case owcimomd gets compromised, 
00289       // we don't want the attacker to be able to wreak havoc on the system as root.
00290       if (!checkRealUser())
00291       {
00292          return INVALID_USER;
00293       }
00294    
00295       // I can't work without euid 0, because only root can change file ownership.
00296       if (::geteuid() != 0)
00297       {
00298          cerr << "owlocalhelper must be setuid root to work" << endl;
00299          return NOT_SETUID_ROOT;
00300       }
00301    
00302       return processStdin();
00303    }
00304    catch (LocalAuthenticationException& e)
00305    {
00306       cerr << e.getMessage() << endl;
00307       return e.getErrorCode();
00308    }
00309    catch (std::exception& e)
00310    {
00311       cerr << "Caught unexpected exception: " << e.what() << endl;
00312       return UNEXPECTED_EXCEPTION;
00313    }
00314    catch (...)
00315    {
00316       cerr << "Caught unexpected exception" << endl;
00317       return UNEXPECTED_EXCEPTION;
00318    }
00319 }
00320 
00321 

Generated on Thu Feb 9 08:48:29 2006 for openwbem by  doxygen 1.4.6