LCOV - code coverage report
Current view: top level - sshd - AliasCommand.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 0 62 0.0 %
Date: 2022-11-19 15:00:39 Functions: 0 6 0.0 %

          Line data    Source code
       1             : // Copyright (C) 2012 The Android Open Source Project
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.sshd;
      16             : 
      17             : import com.google.common.base.Throwables;
      18             : import com.google.common.util.concurrent.Atomics;
      19             : import com.google.gerrit.extensions.api.access.GlobalOrPluginPermission;
      20             : import com.google.gerrit.extensions.restapi.AuthException;
      21             : import com.google.gerrit.server.permissions.GlobalPermission;
      22             : import com.google.gerrit.server.permissions.PermissionBackend;
      23             : import com.google.gerrit.server.permissions.PermissionBackendException;
      24             : import java.io.IOException;
      25             : import java.util.ArrayDeque;
      26             : import java.util.Map;
      27             : import java.util.Set;
      28             : import java.util.concurrent.atomic.AtomicReference;
      29             : import org.apache.sshd.server.Environment;
      30             : import org.apache.sshd.server.channel.ChannelSession;
      31             : import org.apache.sshd.server.command.Command;
      32             : 
      33             : /** Command that executes some other command. */
      34             : public class AliasCommand extends BaseCommand {
      35             :   private final DispatchCommandProvider root;
      36             :   private final PermissionBackend permissionBackend;
      37             :   private final CommandName command;
      38             :   private final AtomicReference<Command> atomicCmd;
      39             : 
      40             :   AliasCommand(
      41             :       @CommandName(Commands.ROOT) DispatchCommandProvider root,
      42             :       PermissionBackend permissionBackend,
      43           0 :       CommandName command) {
      44           0 :     this.root = root;
      45           0 :     this.permissionBackend = permissionBackend;
      46           0 :     this.command = command;
      47           0 :     this.atomicCmd = Atomics.newReference();
      48           0 :   }
      49             : 
      50             :   @Override
      51             :   public void start(ChannelSession channel, Environment env) throws IOException {
      52             :     try {
      53           0 :       begin(channel, env);
      54           0 :     } catch (Failure e) {
      55           0 :       String msg = e.getMessage();
      56           0 :       if (!msg.endsWith("\n")) {
      57           0 :         msg += "\n";
      58             :       }
      59           0 :       err.write(msg.getBytes(ENC));
      60           0 :       err.flush();
      61           0 :       onExit(e.exitCode);
      62           0 :     }
      63           0 :   }
      64             : 
      65             :   private void begin(ChannelSession channel, Environment env) throws IOException, Failure {
      66           0 :     Map<String, CommandProvider> map = root.getMap();
      67           0 :     for (String name : chain(command)) {
      68           0 :       CommandProvider p = map.get(name);
      69           0 :       if (p == null) {
      70           0 :         throw die(getName() + ": not found");
      71             :       }
      72             : 
      73           0 :       Command cmd = p.getProvider().get();
      74           0 :       if (!(cmd instanceof DispatchCommand)) {
      75           0 :         throw die(getName() + ": not found");
      76             :       }
      77           0 :       map = ((DispatchCommand) cmd).getMap();
      78           0 :     }
      79             : 
      80           0 :     CommandProvider p = map.get(command.value());
      81           0 :     if (p == null) {
      82           0 :       throw die(getName() + ": not found");
      83             :     }
      84             : 
      85           0 :     Command cmd = p.getProvider().get();
      86           0 :     checkRequiresCapability(cmd);
      87           0 :     if (cmd instanceof BaseCommand) {
      88           0 :       BaseCommand bc = (BaseCommand) cmd;
      89           0 :       bc.setName(getName());
      90           0 :       bc.setArguments(getArguments());
      91             :     }
      92           0 :     provideStateTo(cmd);
      93           0 :     atomicCmd.set(cmd);
      94           0 :     cmd.start(channel, env);
      95           0 :   }
      96             : 
      97             :   @Override
      98             :   public void destroy(ChannelSession channel) {
      99           0 :     Command cmd = atomicCmd.getAndSet(null);
     100           0 :     if (cmd != null) {
     101             :       try {
     102           0 :         cmd.destroy(channel);
     103           0 :       } catch (Exception e) {
     104           0 :         Throwables.throwIfUnchecked(e);
     105           0 :         throw new RuntimeException(e);
     106           0 :       }
     107             :     }
     108           0 :   }
     109             : 
     110             :   private void checkRequiresCapability(Command cmd) throws Failure {
     111             :     try {
     112           0 :       Set<GlobalOrPluginPermission> check = GlobalPermission.fromAnnotation(cmd.getClass());
     113             :       try {
     114           0 :         permissionBackend.currentUser().checkAny(check);
     115           0 :       } catch (AuthException err) {
     116           0 :         throw new UnloggedFailure(BaseCommand.STATUS_NOT_ADMIN, "fatal: " + err.getMessage());
     117           0 :       }
     118           0 :     } catch (PermissionBackendException err) {
     119           0 :       throw new Failure(1, "fatal: permissions unavailable", err);
     120           0 :     }
     121           0 :   }
     122             : 
     123             :   private static Iterable<String> chain(CommandName command) {
     124           0 :     ArrayDeque<String> chain = new ArrayDeque<>();
     125           0 :     while (command != null) {
     126           0 :       chain.addFirst(command.value());
     127           0 :       command = Commands.parentOf(command);
     128             :     }
     129           0 :     chain.removeLast();
     130           0 :     return chain;
     131             :   }
     132             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750