Repository: mina-sshd Updated Branches: refs/heads/master 7b8152d34 -> f5acda557
[SSHD-776] Do not throw an exception if SSH_MSG_CHANNEL_EOF received for non-existent channel Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/f5acda55 Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/f5acda55 Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/f5acda55 Branch: refs/heads/master Commit: f5acda557a8e818321bfc1dd0c67afa9f9d1dcb6 Parents: 7b8152d Author: Lyor Goldstein <lyor.goldst...@gmail.com> Authored: Wed Oct 4 15:46:33 2017 +0300 Committer: Lyor Goldstein <lyor.goldst...@gmail.com> Committed: Wed Oct 4 15:47:30 2017 +0300 ---------------------------------------------------------------------- .../common/channel/OpenChannelException.java | 53 ------------------- .../channel/exception/SshChannelException.java | 48 +++++++++++++++++ .../exception/SshChannelNotFoundException.java | 39 ++++++++++++++ .../exception/SshChannelOpenException.java | 54 ++++++++++++++++++++ .../helpers/AbstractConnectionService.java | 22 +++++--- .../sshd/server/forward/TcpipServerChannel.java | 6 +-- 6 files changed, 160 insertions(+), 62 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f5acda55/sshd-core/src/main/java/org/apache/sshd/common/channel/OpenChannelException.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/OpenChannelException.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/OpenChannelException.java deleted file mode 100644 index 829858a..0000000 --- a/sshd-core/src/main/java/org/apache/sshd/common/channel/OpenChannelException.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.sshd.common.channel; - -/** - * Documents failure of a channel to open as expected. - * - * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> - */ -public class OpenChannelException extends Exception { - private static final long serialVersionUID = 3861183351970782341L; - private final int code; - - public OpenChannelException(int code, String message) { - this(code, message, null); - } - - public OpenChannelException(int code, String message, Throwable cause) { - super(message, cause); - this.code = code; - } - - /** - * The reason code as specified by RFC 4254. - * <ul> - * <li>{@link org.apache.sshd.common.SshConstants#SSH_OPEN_ADMINISTRATIVELY_PROHIBITED} - * <li>{@link org.apache.sshd.common.SshConstants#SSH_OPEN_CONNECT_FAILED} - * <li>{@link org.apache.sshd.common.SshConstants#SSH_OPEN_UNKNOWN_CHANNEL_TYPE} - * <li>{@link org.apache.sshd.common.SshConstants#SSH_OPEN_RESOURCE_SHORTAGE} - * </ul> - * - * @return reason code; 0 if no standardized reason code is given. - */ - public int getReasonCode() { - return code; - } -} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f5acda55/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelException.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelException.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelException.java new file mode 100644 index 0000000..57c9669 --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelException.java @@ -0,0 +1,48 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sshd.common.channel.exception; + +import java.io.IOException; + +/** + * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> + */ +public class SshChannelException extends IOException { + private static final long serialVersionUID = 7355720478400167933L; + + private final int channelId; + + public SshChannelException(int channelId, String message) { + this(channelId, message, null); + } + + public SshChannelException(int channelId, Throwable cause) { + this(channelId, cause.getMessage(), cause); + } + + public SshChannelException(int channelId, String message, Throwable cause) { + super(message, cause); + this.channelId = channelId; + } + + public int getChannelId() { + return channelId; + } +} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f5acda55/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelNotFoundException.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelNotFoundException.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelNotFoundException.java new file mode 100644 index 0000000..26fb9ab --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelNotFoundException.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.sshd.common.channel.exception; + +/** + * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> + */ +public class SshChannelNotFoundException extends SshChannelException { + private static final long serialVersionUID = 6235323779982884257L; + + public SshChannelNotFoundException(int channelId, String message) { + this(channelId, message, null); + } + + public SshChannelNotFoundException(int channelId, Throwable cause) { + this(channelId, cause.getMessage(), cause); + } + + public SshChannelNotFoundException(int channelId, String message, Throwable cause) { + super(channelId, message, cause); + } +} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f5acda55/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelOpenException.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelOpenException.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelOpenException.java new file mode 100644 index 0000000..e272d2b --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/exception/SshChannelOpenException.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.sshd.common.channel.exception; + +/** + * Documents failure of a channel to open as expected. + * + * @author <a href="mailto:d...@mina.apache.org">Apache MINA SSHD Project</a> + */ +public class SshChannelOpenException extends SshChannelException { + private static final long serialVersionUID = 3591321447714889771L; + + private final int code; + + public SshChannelOpenException(int channelId, int code, String message) { + this(channelId, code, message, null); + } + + public SshChannelOpenException(int channelId, int code, String message, Throwable cause) { + super(channelId, message, cause); + this.code = code; + } + + /** + * The reason code as specified by RFC 4254. + * <ul> + * <li>{@link org.apache.sshd.common.SshConstants#SSH_OPEN_ADMINISTRATIVELY_PROHIBITED} + * <li>{@link org.apache.sshd.common.SshConstants#SSH_OPEN_CONNECT_FAILED} + * <li>{@link org.apache.sshd.common.SshConstants#SSH_OPEN_UNKNOWN_CHANNEL_TYPE} + * <li>{@link org.apache.sshd.common.SshConstants#SSH_OPEN_RESOURCE_SHORTAGE} + * </ul> + * + * @return reason code; 0 if no standardized reason code is given. + */ + public int getReasonCode() { + return code; + } +} http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f5acda55/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java index 32d0920..1524196 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/session/helpers/AbstractConnectionService.java @@ -42,9 +42,10 @@ import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.SshException; import org.apache.sshd.common.channel.AbstractChannel; import org.apache.sshd.common.channel.Channel; -import org.apache.sshd.common.channel.OpenChannelException; import org.apache.sshd.common.channel.RequestHandler; import org.apache.sshd.common.channel.Window; +import org.apache.sshd.common.channel.exception.SshChannelNotFoundException; +import org.apache.sshd.common.channel.exception.SshChannelOpenException; import org.apache.sshd.common.forward.ForwardingFilter; import org.apache.sshd.common.forward.ForwardingFilterFactory; import org.apache.sshd.common.forward.PortForwardingEventListener; @@ -451,8 +452,15 @@ public abstract class AbstractConnectionService<S extends AbstractSession> * @throws IOException if an error occurs */ public void channelEof(Buffer buffer) throws IOException { - Channel channel = getChannel(buffer); - channel.handleEof(); + // Do not use getChannel to avoid the session being closed + // if receiving the SSH_MSG_CHANNEL_EOF on an already closed channel + int recipient = buffer.getInt(); + Channel channel = channels.get(recipient); + if (channel != null) { + channel.handleEof(); + } else { + log.warn("Received SSH_MSG_CHANNEL_EOF on unknown channel " + recipient); + } } /** @@ -523,7 +531,9 @@ public abstract class AbstractConnectionService<S extends AbstractSession> byte[] data = buffer.array(); int curPos = buffer.rpos(); int cmd = (curPos >= 5) ? (data[curPos - 5] & 0xFF) : -1; - throw new SshException("Received " + SshConstants.getCommandMessageName(cmd) + " on unknown channel " + recipient); + // Throw a special exception - SSHD-776 + throw new SshChannelNotFoundException(recipient, + "Received " + SshConstants.getCommandMessageName(cmd) + " on unknown channel " + recipient); } return channel; @@ -583,8 +593,8 @@ public abstract class AbstractConnectionService<S extends AbstractSession> if (exception != null) { String message = exception.getMessage(); int reasonCode = 0; - if (exception instanceof OpenChannelException) { - reasonCode = ((OpenChannelException) exception).getReasonCode(); + if (exception instanceof SshChannelOpenException) { + reasonCode = ((SshChannelOpenException) exception).getReasonCode(); } else { message = exception.getClass().getSimpleName() + " while opening channel: " + message; } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/f5acda55/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java b/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java index cca2eb9..57a5699 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java @@ -33,8 +33,8 @@ import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.channel.Channel; import org.apache.sshd.common.channel.ChannelFactory; import org.apache.sshd.common.channel.ChannelOutputStream; -import org.apache.sshd.common.channel.OpenChannelException; import org.apache.sshd.common.channel.Window; +import org.apache.sshd.common.channel.exception.SshChannelOpenException; import org.apache.sshd.common.future.CloseFuture; import org.apache.sshd.common.io.IoConnectFuture; import org.apache.sshd.common.io.IoConnector; @@ -138,7 +138,7 @@ public class TcpipServerChannel extends AbstractServerChannel { log.debug("doInit(" + this + ")[" + type + "][haveFilter=" + (filter != null) + "] filtered out " + address); } super.close(true); - f.setException(new OpenChannelException(SshConstants.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, "Connection denied")); + f.setException(new SshChannelOpenException(getId(), SshConstants.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, "Connection denied")); return f; } } catch (Error e) { @@ -235,7 +235,7 @@ public class TcpipServerChannel extends AbstractServerChannel { closeImmediately0(); if (problem instanceof ConnectException) { - f.setException(new OpenChannelException(SshConstants.SSH_OPEN_CONNECT_FAILED, problem.getMessage(), problem)); + f.setException(new SshChannelOpenException(getId(), SshConstants.SSH_OPEN_CONNECT_FAILED, problem.getMessage(), problem)); } else { f.setException(problem); }