Search code examples
javasftpjschmainframezos

JSch SFTP put to IBM z/OS fails :failed to write file; nested exception is 3: Permission denied


I am trying to put file via SFTP to mainframe using JSch.

Here is the code:

public void uploadFile(String contents) throws Exception {
    JSch.setLogger(new JSCHLogger());
    connectIfDisconected();
    LOGGER.info("Channel isConnected=: " + channel.isConnected());
    OutputStream os = channel.put("//!DTS4.UP.G5TB4.S60301");
    os.write(contents.getBytes());
    os.flush();
    os.close();
}

protected void connectIfDisconected() throws JSchException {
    if (!session.isConnected()) {
        LOGGER.info(LogEvent.create(".connectIfDisconected()", "Reconnecting session and channel..."));
        session.connect();
        if (channel != null) {
            channel.exit();
        }
        channel = (ChannelSftp) session.openChannel("sftp");
    } else if (!channel.isConnected()) {
        LOGGER.info(LogEvent.create(".connectIfDisconected()", "Reconnecting channel..."));
        channel.connect();
    }
}

Here is the session configuration:

session = jsch.getSession(username, host, port);
Properties config = getProperties(host, port);
session.setConfig(config);
...
...
protected Properties getProperties(String host, int port) throws JSchException {
    Properties config = new Properties();
    config.put("StrictHostKeyChecking", strictHostChecking ? "yes" : "no");
    config.put("kex", "diffie-hellman-group-exchange-sha1");
    config.put("PreferredAuthentications", "password");
    return config;
}

Session is connected fine!

While I'm trying to put file I'm getting the following exception on line

OutputStream os = channel.put(targetFile);
com.three60t.tex.app.exceptions.business.BusinessException: Error while delivering to Client communicator : Permission denied
        at com.three60t.integration.posttrade.utils.DefaultReporter.reportError(DefaultReporter.java:68)
        at com.three60t.integration.posttrade.transformationService.InternalTransformationService.reportError(InternalTransformationService.java:439)
        at com.three60t.integration.posttrade.transformationService.InternalTransformationService.deliver(InternalTransformationService.java:378)
        at com.three60t.integration.posttrade.transformationService.InternalTransformationService.doDeliver(InternalTransformationService.java:314)
        at com.three60t.integration.posttrade.transformationService.InternalTransformationService.transform(InternalTransformationService.java:305)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at com.three60t.tex.communication.message.handler.MessageDispatcher.dispatchToObject(MessageDispatcher.java:722)
        at com.three60t.tex.communication.message.handler.MessageDispatcher.doExecuteObject(MessageDispatcher.java:543)
        at com.three60t.tex.communication.message.handler.MessageDispatcher.access$200(MessageDispatcher.java:77)
        at com.three60t.tex.communication.message.handler.MessageDispatcher$1.run(MessageDispatcher.java:264)
        at com.three60t.tex.communication.message.handler.MessageDispatcher$3.run(MessageDispatcher.java:444)
        at com.three60t.concurrent.executor.v2.RunnableWithTimings.run(RunnableWithTimings.java:81)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: 3: Permission denied
        at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2846)
        at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:753)
        at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:700)
        at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:694)
        at com.three60t.integration.tradeimporters.sftp.DtccSftpClient.uploadFile(DtccSftpClient.java:34)
        at com.three60t.integration.tradeimporters.sftp.SFTPTransportDtcc.upload(SFTPTransportDtcc.java:41)
        at com.three60t.framework.communication.integration.SFTPTransport.upload(SFTPTransport.java:148)
        at com.three60t.integration.tradeimporters.sftp.SFTPTransportDtcc.upload(SFTPTransportDtcc.java:25)
        at com.three60t.integration.tradeimporters.sftp.SFTPTransportDtcc.deliver(SFTPTransportDtcc.java:55)
        at com.three60t.integration.posttrade.transformationService.InternalTransformationService.deliver(InternalTransformationService.java:362)
        ... 15 more

When I'm trying the same using terminal everything works fine!

sftp [email protected]
Connecting to fdmoverspse.dtcc.com...
[email protected]'s password: 
sftp> put myfile.xml //!DTS4.UP.G5TB4.S60301
Uploading myfile.xml to //!DTS4.UP.G5TB4.S60301
myfile.xml       100% 7901     7.7KB/s   00:00   
sftp>

Any ideas how to fix?


Solution

  • There's a "bug" in ChannelSftp.glob_remote that strips the second slash, if the path starts with two slashes.

    Instead of this:

    if(!pattern_has_wildcard){
      if(!dir.equals("/"))
        dir+="/";
      v.addElement(dir+Util.unquote(_pattern));
      return v;
    }
    

    The code should be like:

    if(!pattern_has_wildcard){
      if(foo != 0)
        dir+="/";
      v.addElement(dir+Util.unquote(_pattern));
      return v;
    }