001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache license, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the license for the specific language governing permissions and
015 * limitations under the license.
016 */
017package org.apache.logging.log4j.core.layout;
018
019import java.io.ByteArrayOutputStream;
020import java.io.IOException;
021import java.io.ObjectOutputStream;
022import java.io.OutputStream;
023
024import org.apache.logging.log4j.core.Layout;
025import org.apache.logging.log4j.core.LogEvent;
026import org.apache.logging.log4j.core.config.Node;
027import org.apache.logging.log4j.core.config.plugins.Plugin;
028import org.apache.logging.log4j.core.config.plugins.PluginFactory;
029
030/**
031 * Formats a {@link LogEvent} in its Java serialized form.
032 *
033 * @deprecated Java Serialization has inherent security weaknesses, see https://www.owasp.org/index.php/Deserialization_of_untrusted_data .
034 * Using this layout is no longer recommended. An alternative layout containing the same information is
035 * {@link JsonLayout} when configured with properties="true". Deprecated since 2.9.
036 */
037@Deprecated
038@Plugin(name = "SerializedLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
039public final class SerializedLayout extends AbstractLayout<LogEvent> {
040
041    private static byte[] serializedHeader;
042
043    static {
044        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
045        try {
046            new ObjectOutputStream(baos).close();
047            serializedHeader = baos.toByteArray();
048        } catch (final Exception ex) {
049            LOGGER.error("Unable to generate Object stream header", ex);
050        }
051    }
052
053    private SerializedLayout() {
054        super(null, null, null);
055        LOGGER.warn("SerializedLayout is deprecated due to the inherent security weakness in Java Serialization, see https://www.owasp.org/index.php/Deserialization_of_untrusted_data Consider using another layout, e.g. JsonLayout");
056    }
057
058    /**
059     * Formats a {@link org.apache.logging.log4j.core.LogEvent} as a serialized byte array of the LogEvent object.
060     *
061     * @param event The LogEvent.
062     * @return the formatted LogEvent.
063     */
064    @Override
065    public byte[] toByteArray(final LogEvent event) {
066        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
067        try (final ObjectOutputStream oos = new PrivateObjectOutputStream(baos)) {
068            oos.writeObject(event);
069            oos.reset();
070        } catch (final IOException ioe) {
071            LOGGER.error("Serialization of LogEvent failed.", ioe);
072        }
073        return baos.toByteArray();
074    }
075
076    /**
077     * Returns the LogEvent.
078     *
079     * @param event The Logging Event.
080     * @return The LogEvent.
081     */
082    @Override
083    public LogEvent toSerializable(final LogEvent event) {
084        return event;
085    }
086
087    /**
088     * Creates a SerializedLayout.
089     * @return A SerializedLayout.
090     */
091    @Deprecated
092    @PluginFactory
093    public static SerializedLayout createLayout() {
094        return new SerializedLayout();
095    }
096
097    @Override
098    public byte[] getHeader() {
099        return serializedHeader;
100    }
101
102    /**
103     * SerializedLayout returns a binary stream.
104     * @return The content type.
105     */
106    @Override
107    public String getContentType() {
108        return "application/octet-stream";
109    }
110
111    /**
112     * The stream header will be written in the Manager so skip it here.
113     */
114    private class PrivateObjectOutputStream extends ObjectOutputStream {
115
116        public PrivateObjectOutputStream(final OutputStream os) throws IOException {
117            super(os);
118        }
119
120        @Override
121        protected void writeStreamHeader() {
122            // do nothing
123        }
124    }
125}