blob: 77ae1a7ec7303d89a6e7ebe57b2c6aaf95c0b837 [file] [log] [blame]
Yi Jinc23fad22017-09-15 17:24:59 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18
19#include "PrivacyBuffer.h"
20#include "io_util.h"
21
22#include <android/util/protobuf.h>
Yi Jinc23fad22017-09-15 17:24:59 -070023
24using namespace android::util;
25
26/**
27 * Write the field to buf based on the wire type, iterator will point to next field.
28 * If skip is set to true, no data will be written to buf. Return number of bytes written.
29 */
Yi Jin42711a02017-10-11 18:20:24 -070030void
31PrivacyBuffer::writeFieldOrSkip(uint32_t fieldTag, bool skip)
Yi Jinc23fad22017-09-15 17:24:59 -070032{
Yi Jin42711a02017-10-11 18:20:24 -070033 uint8_t wireType = read_wire_type(fieldTag);
Yi Jinc23fad22017-09-15 17:24:59 -070034 size_t bytesToWrite = 0;
Yi Jin42711a02017-10-11 18:20:24 -070035 uint32_t varint = 0;
36
Yi Jinc23fad22017-09-15 17:24:59 -070037 switch (wireType) {
38 case WIRE_TYPE_VARINT:
Yi Jin42711a02017-10-11 18:20:24 -070039 varint = mData.readRawVarint();
40 if (!skip) {
41 mProto.writeRawVarint(fieldTag);
42 mProto.writeRawVarint(varint);
43 }
44 return;
Yi Jinc23fad22017-09-15 17:24:59 -070045 case WIRE_TYPE_FIXED64:
Yi Jin42711a02017-10-11 18:20:24 -070046 if (!skip) mProto.writeRawVarint(fieldTag);
Yi Jinc23fad22017-09-15 17:24:59 -070047 bytesToWrite = 8;
48 break;
49 case WIRE_TYPE_LENGTH_DELIMITED:
Yi Jin42711a02017-10-11 18:20:24 -070050 bytesToWrite = mData.readRawVarint();
51 if(!skip) mProto.writeLengthDelimitedHeader(read_field_id(fieldTag), bytesToWrite);
Yi Jinc23fad22017-09-15 17:24:59 -070052 break;
53 case WIRE_TYPE_FIXED32:
Yi Jin42711a02017-10-11 18:20:24 -070054 if (!skip) mProto.writeRawVarint(fieldTag);
Yi Jinc23fad22017-09-15 17:24:59 -070055 bytesToWrite = 4;
56 break;
57 }
58 if (skip) {
Yi Jin42711a02017-10-11 18:20:24 -070059 mData.rp()->move(bytesToWrite);
Yi Jinc23fad22017-09-15 17:24:59 -070060 } else {
61 for (size_t i=0; i<bytesToWrite; i++) {
Yi Jin42711a02017-10-11 18:20:24 -070062 mProto.writeRawByte(mData.next());
Yi Jinc23fad22017-09-15 17:24:59 -070063 }
64 }
Yi Jinc23fad22017-09-15 17:24:59 -070065}
66
67/**
68 * Strip next field based on its private policy and request spec, then stores data in buf.
69 * Return NO_ERROR if succeeds, otherwise BAD_VALUE is returned to indicate bad data in FdBuffer.
70 *
71 * The iterator must point to the head of a protobuf formatted field for successful operation.
72 * After exit with NO_ERROR, iterator points to the next protobuf field's head.
73 */
Yi Jin42711a02017-10-11 18:20:24 -070074status_t
75PrivacyBuffer::stripField(const Privacy* parentPolicy, const PrivacySpec& spec)
Yi Jinc23fad22017-09-15 17:24:59 -070076{
Yi Jin42711a02017-10-11 18:20:24 -070077 if (!mData.hasNext() || parentPolicy == NULL) return BAD_VALUE;
78 uint32_t fieldTag = mData.readRawVarint();
79 const Privacy* policy = parentPolicy->lookup(read_field_id(fieldTag));
80
Yi Jinc23fad22017-09-15 17:24:59 -070081 if (policy == NULL || !policy->IsMessageType() || !policy->HasChildren()) {
82 bool skip = !spec.CheckPremission(policy);
Yi Jin42711a02017-10-11 18:20:24 -070083 // iterator will point to head of next field
84 writeFieldOrSkip(fieldTag, skip);
85 return NO_ERROR;
Yi Jinc23fad22017-09-15 17:24:59 -070086 }
87 // current field is message type and its sub-fields have extra privacy policies
Yi Jin42711a02017-10-11 18:20:24 -070088 uint32_t msgSize = mData.readRawVarint();
89 EncodedBuffer::Pointer start = mData.rp()->copy();
Yi Jinbe6de302017-10-24 12:30:24 -070090 long long token = mProto.start(policy->EncodedFieldId());
Yi Jin42711a02017-10-11 18:20:24 -070091 while (mData.rp()->pos() - start.pos() != msgSize) {
Yi Jin42711a02017-10-11 18:20:24 -070092 status_t err = stripField(policy, spec);
Yi Jinc23fad22017-09-15 17:24:59 -070093 if (err != NO_ERROR) return err;
Yi Jinc23fad22017-09-15 17:24:59 -070094 }
Yi Jinbe6de302017-10-24 12:30:24 -070095 mProto.end(token);
Yi Jinc23fad22017-09-15 17:24:59 -070096 return NO_ERROR;
97}
98
99// ================================================================================
100PrivacyBuffer::PrivacyBuffer(const Privacy* policy, EncodedBuffer::iterator& data)
101 :mPolicy(policy),
102 mData(data),
Yi Jin42711a02017-10-11 18:20:24 -0700103 mProto(),
Yi Jinc23fad22017-09-15 17:24:59 -0700104 mSize(0)
105{
106}
107
108PrivacyBuffer::~PrivacyBuffer()
109{
110}
111
112status_t
113PrivacyBuffer::strip(const PrivacySpec& spec)
114{
115 // optimization when no strip happens
116 if (mPolicy == NULL || !mPolicy->HasChildren() || spec.RequireAll()) {
117 if (spec.CheckPremission(mPolicy)) mSize = mData.size();
118 return NO_ERROR;
119 }
120 while (mData.hasNext()) {
Yi Jin42711a02017-10-11 18:20:24 -0700121 status_t err = stripField(mPolicy, spec);
Yi Jinc23fad22017-09-15 17:24:59 -0700122 if (err != NO_ERROR) return err;
123 }
124 if (mData.bytesRead() != mData.size()) return BAD_VALUE;
Yi Jin42711a02017-10-11 18:20:24 -0700125 mSize = mProto.size();
Yi Jinc23fad22017-09-15 17:24:59 -0700126 mData.rp()->rewind(); // rewind the read pointer back to beginning after the strip.
127 return NO_ERROR;
128}
129
130void
131PrivacyBuffer::clear()
132{
133 mSize = 0;
Yi Jin42711a02017-10-11 18:20:24 -0700134 mProto = ProtoOutputStream();
Yi Jinc23fad22017-09-15 17:24:59 -0700135}
136
137size_t
138PrivacyBuffer::size() const { return mSize; }
139
140status_t
141PrivacyBuffer::flush(int fd)
142{
143 status_t err = NO_ERROR;
Yi Jin42711a02017-10-11 18:20:24 -0700144 EncodedBuffer::iterator iter = size() == mData.size() ? mData : mProto.data();
Yi Jinc23fad22017-09-15 17:24:59 -0700145 while (iter.readBuffer() != NULL) {
146 err = write_all(fd, iter.readBuffer(), iter.currentToRead());
147 iter.rp()->move(iter.currentToRead());
148 if (err != NO_ERROR) return err;
149 }
150 return NO_ERROR;
151}