def getHttpAuth(req): # special header to pass a session id through # instead of a real http authorization token if 'X-Session-Id' in req.headers: return req.headers['X-Session-Id'] # pysid cookies are just as good as the session id - flex uses the browser # for authentication info and cookies are sent for free. (RBL-4276) if 'pysid' in req.cookies: return req.cookies['pysid'] return webauth.getAuth(req)
def _getResponse(self): self.authToken = auth = getAuth(self.request) if auth is None: return self._requestAuth("Invalid authentication token") # Repository setup self.serverNameList = self.repServer.serverNameList cfg = conarycfg.ConaryConfiguration(readConfigFiles=False) cfg.repositoryMap = self.repServer.map for serverName in self.serverNameList: cfg.user.addServerGlob(serverName, auth[0], auth[1]) self.repos = shimclient.ShimNetClient( server=self.repServer, protocol=self.request.scheme, port=self.request.server_port, authToken=auth, repMap=cfg.repositoryMap, userMap=cfg.user, ) # Check if the request is sane methodName = self.request.path_info_peek() or 'main' method = None if methodName and methodName[0] != '_': method = getattr(self, methodName, None) if not method: raise exc.HTTPNotFound() self.methodName = methodName # Do authn/authz checks if auth[0] != 'anonymous': self.loggedIn = self.repServer.auth.checkPassword(auth) if not self.loggedIn: return self._requestAuth() else: self.loggedIn = False # Run the method self.hasWrite = self.repServer.auth.check(auth, write=True) self.isAdmin = self.repServer.auth.authCheck(auth, admin=True) params = self.request.params.mixed() try: result = method(auth=auth, **params) except (exc.HTTPForbidden, errors.InsufficientPermission): if self.loggedIn: raise exc.HTTPForbidden() else: return self._requestAuth() except WebError, err: result = self._write("error", error=str(err))
def post(port, isSecure, repos, req, authToken=None, repServer=None): if authToken is None: authToken = getAuth(req) if authToken is None: return apache.HTTP_BAD_REQUEST if authToken[0] != "anonymous" and not isSecure and repos.cfg.forceSSL: return apache.HTTP_FORBIDDEN if isSecure: protocol = "https" else: protocol = "http" extraInfo = None repos.log.reset() if req.headers_in['Content-Type'] == "text/xml": # handle XML-RPC requests encoding = req.headers_in.get('Content-Encoding', None) sio = util.BoundedStringIO() try: util.copyStream(req, sio) except IOError, e: # if we got a read timeout, marshal an exception back # to the client print >> sys.stderr, 'error reading from client: %s' % e method = 'unknown - client timeout' response = xmlshims.ResponseArgs.newException( 'ClientTimeout', 'The server was not able to read the ' 'XML-RPC request sent by this client. ' 'This is sometimes caused by MTU problems ' 'on your network connection. Using a ' 'smaller MTU may work around this ' 'problem.') headers = {} startTime = time.time() else: # otherwise, we've read the data, let's process it if encoding == 'deflate': sio.seek(0) try: sio = util.decompressStream(sio) except zlib.error, error: req.log_error("zlib inflate error in POST: %s" % error) return apache.HTTP_BAD_REQUEST startTime = time.time() sio.seek(0) try: (params, method) = util.xmlrpcLoad(sio) except: req.log_error('error parsing XMLRPC request') return apache.HTTP_BAD_REQUEST repos.log(3, "decoding=%s" % method, authToken[0], "%.3f" % (time.time() - startTime)) # req.connection.local_addr[0] is the IP address the server # listens on, not the IP address of the accepted socket. Most of # the times it will be 0.0.0.0 which is not very useful. We're # using local_ip instead, and we grab just the port from # local_addr. localAddr = "%s:%s" % (req.connection.local_ip, req.connection.local_addr[1]) remoteIp = req.connection.remote_ip # Get the IP address of the original request in the case # of a proxy, otherwise use the connection's remote_ip if 'X-Forwarded-For' in req.headers_in: # pick the right-most client, since that is # the one closest to us. For example, if # we have "X-Forwarded-For: 1.2.3.4, 4.5.6.7" # we want to use 4.5.6.7 clients = req.headers_in['X-Forwarded-For'] remoteIp = clients.split(',')[-1].strip() try: request = xmlshims.RequestArgs.fromWire(params) except (TypeError, ValueError, IndexError): req.log_error('error parsing XMLRPC arguments') return apache.HTTP_BAD_REQUEST try: response, extraInfo = repos.callWrapper( protocol=protocol, port=port, methodname=method, authToken=authToken, request=request, remoteIp=remoteIp, rawUrl=req.unparsed_uri, localAddr=localAddr, protocolString=req.protocol, headers=req.headers_in, isSecure=isSecure, ) except errors.InsufficientPermission: return apache.HTTP_FORBIDDEN
def get(port, isSecure, repos, req, restHandler=None, authToken=None, repServer=None): uri = req.uri if uri.endswith('/'): uri = uri[:-1] cmd = os.path.basename(uri) if authToken is None: authToken = getAuth(req) if authToken is None: return apache.HTTP_BAD_REQUEST if authToken[0] != "anonymous" and not isSecure and repos.cfg.forceSSL: return apache.HTTP_FORBIDDEN if restHandler and uri.startswith(restHandler.prefix): return restHandler.handle(req, req.unparsed_uri) elif cmd == "changeset": if not req.args: # the client asked for a changeset, but there is no # ?tmpXXXXXX.cf after /conary/changeset (CNY-1142) return apache.HTTP_BAD_REQUEST if '/' in req.args: return apache.HTTP_FORBIDDEN localName = repos.tmpPath + "/" + req.args + "-out" if localName.endswith(".cf-out"): try: f = open(localName, "r") except IOError: return apache.HTTP_NOT_FOUND os.unlink(localName) items = [] totalSize = 0 for l in f.readlines(): (path, size, isChangeset, preserveFile) = l.split() size = int(size) isChangeset = int(isChangeset) preserveFile = int(preserveFile) totalSize += size items.append((path, size, isChangeset, preserveFile)) f.close() del f else: try: size = os.stat(localName).st_size except OSError: return apache.HTTP_NOT_FOUND items = [(localName, size, 0, 0)] totalSize = size # TODO: refactor to use proxy.ChangesetFileReader readNestedFile = proxy.ChangesetFileReader.readNestedFile req.content_type = "application/x-conary-change-set" req.set_content_length(totalSize) for (path, size, isChangeset, preserveFile) in items: if isChangeset: cs = FileContainer(util.ExtendedFile(path, buffering=False)) try: for data in cs.dumpIter(readNestedFile, args=(repos.getContentsStore(), )): req.write(data) except IOError, err: log.error("IOError dumping changeset: %s" % err) return apache.HTTP_BAD_REQUEST del cs else: sendfile(req, size, path) if not preserveFile: os.unlink(path) return apache.OK
def post(port, isSecure, repos, req, authToken=None, repServer=None): if authToken is None: authToken = getAuth(req) if authToken is None: return apache.HTTP_BAD_REQUEST if authToken[0] != "anonymous" and not isSecure and repos.cfg.forceSSL: return apache.HTTP_FORBIDDEN if isSecure: protocol = "https" else: protocol = "http" extraInfo = None repos.log.reset() if req.headers_in['Content-Type'] == "text/xml": # handle XML-RPC requests encoding = req.headers_in.get('Content-Encoding', None) sio = util.BoundedStringIO() try: util.copyStream(req, sio) except IOError, e: # if we got a read timeout, marshal an exception back # to the client print >> sys.stderr, 'error reading from client: %s' %e method = 'unknown - client timeout' response = xmlshims.ResponseArgs.newException('ClientTimeout', 'The server was not able to read the ' 'XML-RPC request sent by this client. ' 'This is sometimes caused by MTU problems ' 'on your network connection. Using a ' 'smaller MTU may work around this ' 'problem.') headers = {} startTime = time.time() else: # otherwise, we've read the data, let's process it if encoding == 'deflate': sio.seek(0) try: sio = util.decompressStream(sio) except zlib.error, error: req.log_error("zlib inflate error in POST: %s" % error) return apache.HTTP_BAD_REQUEST startTime = time.time() sio.seek(0) try: (params, method) = util.xmlrpcLoad(sio) except: req.log_error('error parsing XMLRPC request') return apache.HTTP_BAD_REQUEST repos.log(3, "decoding=%s" % method, authToken[0], "%.3f" % (time.time()-startTime)) # req.connection.local_addr[0] is the IP address the server # listens on, not the IP address of the accepted socket. Most of # the times it will be 0.0.0.0 which is not very useful. We're # using local_ip instead, and we grab just the port from # local_addr. localAddr = "%s:%s" % (req.connection.local_ip, req.connection.local_addr[1]) remoteIp = req.connection.remote_ip # Get the IP address of the original request in the case # of a proxy, otherwise use the connection's remote_ip if 'X-Forwarded-For' in req.headers_in: # pick the right-most client, since that is # the one closest to us. For example, if # we have "X-Forwarded-For: 1.2.3.4, 4.5.6.7" # we want to use 4.5.6.7 clients = req.headers_in['X-Forwarded-For'] remoteIp = clients.split(',')[-1].strip() try: request = xmlshims.RequestArgs.fromWire(params) except (TypeError, ValueError, IndexError): req.log_error('error parsing XMLRPC arguments') return apache.HTTP_BAD_REQUEST try: response, extraInfo = repos.callWrapper( protocol=protocol, port=port, methodname=method, authToken=authToken, request=request, remoteIp=remoteIp, rawUrl=req.unparsed_uri, localAddr=localAddr, protocolString=req.protocol, headers=req.headers_in, isSecure=isSecure, ) except errors.InsufficientPermission: return apache.HTTP_FORBIDDEN
def get(port, isSecure, repos, req, restHandler=None, authToken=None, repServer=None): uri = req.uri if uri.endswith('/'): uri = uri[:-1] cmd = os.path.basename(uri) if authToken is None: authToken = getAuth(req) if authToken is None: return apache.HTTP_BAD_REQUEST if authToken[0] != "anonymous" and not isSecure and repos.cfg.forceSSL: return apache.HTTP_FORBIDDEN if restHandler and uri.startswith(restHandler.prefix): return restHandler.handle(req, req.unparsed_uri) elif cmd == "changeset": if not req.args: # the client asked for a changeset, but there is no # ?tmpXXXXXX.cf after /conary/changeset (CNY-1142) return apache.HTTP_BAD_REQUEST if '/' in req.args: return apache.HTTP_FORBIDDEN localName = repos.tmpPath + "/" + req.args + "-out" if localName.endswith(".cf-out"): try: f = open(localName, "r") except IOError: return apache.HTTP_NOT_FOUND os.unlink(localName) items = [] totalSize = 0 for l in f.readlines(): (path, size, isChangeset, preserveFile) = l.split() size = int(size) isChangeset = int(isChangeset) preserveFile = int(preserveFile) totalSize += size items.append((path, size, isChangeset, preserveFile)) f.close() del f else: try: size = os.stat(localName).st_size; except OSError: return apache.HTTP_NOT_FOUND items = [ (localName, size, 0, 0) ] totalSize = size # TODO: refactor to use proxy.ChangesetFileReader readNestedFile = proxy.ChangesetFileReader.readNestedFile req.content_type = "application/x-conary-change-set" req.set_content_length(totalSize) for (path, size, isChangeset, preserveFile) in items: if isChangeset: cs = FileContainer(util.ExtendedFile(path, buffering=False)) try: for data in cs.dumpIter(readNestedFile, args=(repos.getContentsStore(),)): req.write(data) except IOError, err: log.error("IOError dumping changeset: %s" % err) return apache.HTTP_BAD_REQUEST del cs else: sendfile(req, size, path) if not preserveFile: os.unlink(path) return apache.OK